Integrating master direct pacakge [BREAKING CHANGES] (#97)

* a draft version

* One more draft

* Simple namespace and code removal changes

* New REST contract types

* Some more contract changes

* Moving type conversion to new CosmosResource

* Some more contract changes

* Dance between different resource types

* Committing a binary diff

* Test project changes

* Cosmos tests building

* Tests green

* CosmosResource as base type removed and required properties are in-lined

AltLink is removed from all resources and also consumption constructs them on-demand.

* Committing local project system changes as well.

* New contract validation tests for database and container to match old contracts

Leveraged C# 6.0 syntax to clean-up default initialization code
PartitionKeyRangeStatisc type removed from contracts

Future work:
1. SchemaBuilderPolicy
2. SpatialSpec
3. CompositePaths

* RequestOptions excluded from GitHub

Mainfest bug fix (all UT GREEN now)

* Some more emulator cmpilation fixes

* Emulator project building

* Integrated into new StoreClientFactory

* Some more test fixes

* All except performance GREEN

* Including missing file

* Ignoring all quarantines tests

* All emulator tests GREEN

* All solution GREEN

* Including JsonNavigator code

Also all solution builds GREEN

* Cosmos regions & Proximity utils moved to Direct.

Offer tests fixed.

* Moving UT into unit-tests project.

* Removing TestJosns from Test FX project

* Solition and project file changes refresh
This commit is contained in:
kirankumarkolli 2019-03-28 04:17:17 +05:30 коммит произвёл GitHub
Родитель 175a52286d
Коммит 5ce792f507
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
339 изменённых файлов: 14886 добавлений и 9401 удалений

Просмотреть файл

@ -27,7 +27,6 @@ namespace Microsoft.Azure.Cosmos
/// </example>
/// <seealso cref="AccessConditionType"/>
/// <seealso cref="RequestOptions"/>
/// <seealso cref="CosmosResource"/>
public sealed class AccessCondition
{
/// <summary>
@ -44,7 +43,6 @@ namespace Microsoft.Azure.Cosmos
/// <value>
/// The value of the condition. For <see cref="AccessConditionType"/> IfMatch and IfNotMatch, this is the ETag that has to be compared to.
/// </value>
/// <seealso cref="CosmosResource"/>
public string Condition { get; set; }
}
}

Просмотреть файл

@ -4,7 +4,6 @@
using System.Runtime.CompilerServices;
#if !SignAssembly
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Tests")]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.EmulatorTests")]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends.Tests")]
@ -14,26 +13,3 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.NetFramework.Tests")]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Performance.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyRef.MoqPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.EmulatorTests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Extensions.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Extensions" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.NetFramework.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Tests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.EmulatorTests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends.Tests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Extensions.Tests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Extensions" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.NetFramework.Tests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Table" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Table" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Table.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Table.Tests" + AssemblyRef.TestPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Performance.Tests" + AssemblyRef.ProductPublicKey)]
[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Performance.Tests" + AssemblyRef.TestPublicKey)]

Просмотреть файл

@ -5,6 +5,8 @@ namespace Microsoft.Azure.Cosmos
{
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos
using System.Runtime.InteropServices;
using System.Security;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal static class Base64Helper
{

Просмотреть файл

@ -4,6 +4,7 @@
namespace Microsoft.Azure.Cosmos
{
using System;
using Microsoft.Azure.Documents;
/// <summary>
/// Specifies the options associated with change feed methods (enumeration operations) in the Azure Cosmos DB service.

Просмотреть файл

@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
/// <summary>
/// This retry policy is designed to work with in a pair with ClientRetryPolicy.

Просмотреть файл

@ -16,6 +16,8 @@ namespace Microsoft.Azure.Cosmos
#if !NETSTANDARD16
using System.Diagnostics;
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents;
#endif
internal static class ClientExtensions
@ -112,7 +114,7 @@ namespace Microsoft.Azure.Cosmos
if (string.Equals(responseMessage.Content?.Headers?.ContentType?.MediaType, ClientExtensions.MediaTypeJson, StringComparison.OrdinalIgnoreCase))
{
Stream readStream = await responseMessage.Content.ReadAsStreamAsync();
Error error = CosmosResource.LoadFrom<Error>(readStream);
Error error = Resource.LoadFrom<Error>(readStream);
return new DocumentClientException(
error,
responseMessage.Headers,

Просмотреть файл

@ -10,6 +10,7 @@
namespace Microsoft.Azure.Cosmos {
using System;
using System.Reflection;
/// <summary>
@ -39,7 +40,7 @@ namespace Microsoft.Azure.Cosmos {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Cosmos.ClientResources", typeof(ClientResources).GetAssembly());
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Cosmos.ClientResources", typeof(ClientResources).GetTypeInfo().Assembly);
resourceMan = temp;
}

Просмотреть файл

@ -12,6 +12,8 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
/// <summary>
/// Client policy is combination of endpoint change retry + throttling retry.
/// </summary>

Просмотреть файл

@ -8,6 +8,8 @@ namespace Microsoft.Azure.Cosmos
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
/// <summary>
/// Represents the connection policy associated with a DocumentClient to connect to the Azure Cosmos DB service.

Просмотреть файл

@ -227,7 +227,7 @@ namespace Microsoft.Azure.Cosmos
);
// DocumentClient is not initialized with any consistency overrides so default is backend consistency
this.AccountConsistencyLevel = this.DocumentClient.ConsistencyLevel;
this.AccountConsistencyLevel = (ConsistencyLevel)this.DocumentClient.ConsistencyLevel;
this.RequestHandler = clientPipelineBuilder.Build();
this.Databases = new CosmosDatabases(this);

Просмотреть файл

@ -8,6 +8,8 @@ namespace Microsoft.Azure.Cosmos
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
/// <summary>
/// This is a Builder class that creates a cosmos client

Просмотреть файл

@ -9,6 +9,8 @@ namespace Microsoft.Azure.Cosmos
using System.Data.Common;
using System.Linq;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Newtonsoft.Json;
/// <summary>

Просмотреть файл

@ -14,8 +14,11 @@ namespace Microsoft.Azure.Cosmos
/// </summary>
internal class CosmosDefaultJsonSerializer : CosmosJsonSerializer
{
private static readonly JsonSerializer Serializer = new JsonSerializer();
private static readonly Encoding DefaultEncoding = new UTF8Encoding(false, true);
private static readonly JsonSerializer Serializer = new JsonSerializer()
{
NullValueHandling = NullValueHandling.Ignore,
};
public override T FromStream<T>(Stream stream)
{

Просмотреть файл

@ -1,266 +0,0 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
/// <summary>
/// The Azure regions that are currently supported by the Azure Cosmos DB service.
/// </summary>
public static class CosmosRegions
{
/// <summary>
/// Name of the Azure West US region in the Azure Cosmos DB service.
/// </summary>
public const string WestUS = "West US";
/// <summary>
/// Name of the Azure West US 2 region in the Azure Cosmos DB service.
/// </summary>
public const string WestUS2 = "West US 2";
/// <summary>
/// Name of the Azure West Central US region in the Azure Cosmos DB service.
/// </summary>
public const string WestCentralUS = "West Central US";
/// <summary>
/// Name of the Azure East US region in the Azure Cosmos DB service.
/// </summary>
public const string EastUS = "East US";
/// <summary>
/// Name of the Azure East US 2 region in the Azure Cosmos DB service.
/// </summary>
public const string EastUS2 = "East US 2";
/// <summary>
/// Name of the Azure Central US region in the Azure Cosmos DB service.
/// </summary>
public const string CentralUS = "Central US";
/// <summary>
/// Name of the Azure Sourth Central US region in the Azure Cosmos DB service.
/// </summary>
public const string SouthCentralUS = "South Central US";
/// <summary>
/// Name of the Azure North Central US region in the Azure Cosmos DB service.
/// </summary>
public const string NorthCentralUS = "North Central US";
/// <summary>
/// Name of the Azure West Europe region in the Azure Cosmos DB service.
/// </summary>
public const string WestEurope = "West Europe";
/// <summary>
/// Name of the Azure North Europe region in the Azure Cosmos DB service.
/// </summary>
public const string NorthEurope = "North Europe";
/// <summary>
/// Name of the Azure East Asia region in the Azure Cosmos DB service.
/// </summary>
public const string EastAsia = "East Asia";
/// <summary>
/// Name of the Azure Southeast Asia region in the Azure Cosmos DB service.
/// </summary>
public const string SoutheastAsia = "Southeast Asia";
/// <summary>
/// Name of the Azure Japan East region in the Azure Cosmos DB service.
/// </summary>
public const string JapanEast = "Japan East";
/// <summary>
/// Name of the Azure Japan West region in the Azure Cosmos DB service.
/// </summary>
public const string JapanWest = "Japan West";
/// <summary>
/// Name of the Azure Australia East region in the Azure Cosmos DB service.
/// </summary>
public const string AustraliaEast = "Australia East";
/// <summary>
/// Name of the Azure Australia Southeast region in the Azure Cosmos DB service.
/// </summary>
public const string AustraliaSoutheast = "Australia Southeast";
/// <summary>
/// Name of the Azure Central India region in the Azure Cosmos DB service.
/// </summary>
public const string CentralIndia = "Central India";
/// <summary>
/// Name of the Azure South India region in the Azure Cosmos DB service.
/// </summary>
public const string SouthIndia = "South India";
/// <summary>
/// Name of the Azure West India region in the Azure Cosmos DB service.
/// </summary>
public const string WestIndia = "West India";
/// <summary>
/// Name of the Azure Canada East region in the Azure Cosmos DB service.
/// </summary>
public const string CanadaEast = "Canada East";
/// <summary>
/// Name of the Azure Canada Central region in the Azure Cosmos DB service.
/// </summary>
public const string CanadaCentral = "Canada Central";
/// <summary>
/// Name of the Azure Germany Central region in the Azure Cosmos DB service.
/// </summary>
public const string GermanyCentral = "Germany Central";
/// <summary>
/// Name of the Azure Germany Northeast region in the Azure Cosmos DB service.
/// </summary>
public const string GermanyNortheast = "Germany Northeast";
/// <summary>
/// Name of the Azure China North region in the Azure Cosmos DB service.
/// </summary>
public const string ChinaNorth = "China North";
/// <summary>
/// Name of the Azure China East region in the Azure Cosmos DB service.
/// </summary>
public const string ChinaEast = "China East";
/// <summary>
/// Name of the Azure China North 2 region in the Azure Cosmos DB service.
/// </summary>
public const string ChinaNorth2 = "China North 2";
/// <summary>
/// Name of the Azure China East 2 region in the Azure Cosmos DB service.
/// </summary>
public const string ChinaEast2 = "China East 2";
/// <summary>
/// Name of the Azure Korea South region in the Azure Cosmos DB service.
/// </summary>
public const string KoreaSouth = "Korea South";
/// <summary>
/// Name of the Azure Korea Central region in the Azure Cosmos DB service.
/// </summary>
public const string KoreaCentral = "Korea Central";
/// <summary>
/// Name of the Azure UK West region in the Azure Cosmos DB service.
/// </summary>
public const string UKWest = "UK West";
/// <summary>
/// Name of the Azure UK South region in the Azure Cosmos DB service.
/// </summary>
public const string UKSouth = "UK South";
/// <summary>
/// Name of the Azure Brazil South region in the Azure Cosmos DB service.
/// </summary>
public const string BrazilSouth = "Brazil South";
/// <summary>
/// Name of the Azure USGov Arizona region in the Azure Cosmos DB service.
/// </summary>
public const string USGovArizona = "USGov Arizona";
/// <summary>
/// Name of the Azure USGov Texas region in the Azure Cosmos DB service.
/// </summary>
public const string USGovTexas = "USGov Texas";
/// <summary>
/// Name of the Azure USGov Virginia region in the Azure Cosmos DB service.
/// </summary>
public const string USGovVirginia = "USGov Virginia";
/// <summary>
/// Name of the Azure East US 2 EUAP region in the Azure Cosmos DB service.
/// </summary>
public const string EastUS2EUAP = "East US 2 EUAP";
/// <summary>
/// Name of the Azure Central US EUAP region in the Azure Cosmos DB service.
/// </summary>
public const string CentralUSEUAP = "Central US EUAP";
/// <summary>
/// Name of the Azure France Central region in the Azure Cosmos DB service.
/// </summary>
public const string FranceCentral = "France Central";
/// <summary>
/// Name of the Azure France South region in the Azure Cosmos DB service.
/// </summary>
public const string FranceSouth = "France South";
/// <summary>
/// Name of the Azure DoD Central region in the Azure Cosmos DB service.
/// </summary>
public const string USDoDCentral = "USDoD Central";
/// <summary>
/// Name of the Azure DoD East region in the Azure Cosmos DB service.
/// </summary>
public const string USDoDEast = "USDoD East";
/// <summary>
/// Name of the Azure Australia Central region in the Azure Cosmos DB service.
/// </summary>
public const string AustraliaCentral = "Australia Central";
/// <summary>
/// Name of the Azure Australia Central 2 region in the Azure Cosmos DB service.
/// </summary>
public const string AustraliaCentral2 = "Australia Central 2";
/// <summary>
/// Name of the Azure South Africa North region in the Azure Cosmos DB service.
/// </summary>
public const string SouthAfricaNorth = "South Africa North";
/// <summary>
/// Name of the Azure South Africa West region in the Azure Cosmos DB service.
/// </summary>
public const string SouthAfricaWest = "South Africa West";
/// <summary>
/// Name of the Azure UAE Central region in the Azure Cosmos DB service.
/// </summary>
public const string UAECentral = "UAE Central";
/// <summary>
/// Name of the Azure UAE North region in the Azure Cosmos DB service.
/// </summary>
public const string UAENorth = "UAE North";
/// <summary>
/// Name of the Azure USNat East region in the Azure Cosmos DB service.
/// </summary>
public const string USNatEast = "USNat East";
/// <summary>
/// Name of the Azure USNat West region in the Azure Cosmos DB service.
/// </summary>
public const string USNatWest = "USNat West";
/// <summary>
/// Name of the Azure USSec East region in the Azure Cosmos DB service.
/// </summary>
public const string USSecEast = "USSec East";
/// <summary>
/// Name of the Azure USNat West region in the Azure Cosmos DB service.
/// </summary>
public const string USSecWest = "USSec West";
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos
using System.Diagnostics.Tracing;
using System.Net.Http.Headers;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
[EventSource(Name = "DocumentDBClient", Guid = "f832a342-0a53-5bab-b57b-d5bc65319768")]
// Marking it as non-sealed in order to unit test it using Moq framework

Просмотреть файл

@ -11,8 +11,9 @@ namespace Microsoft.Azure.Cosmos
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Linq;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider
{
@ -45,7 +46,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="documentCollection">the Microsoft.Azure.Documents.DocumentCollection object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosContainerSettings>> CreateDocumentCollectionAsync(Uri databaseUri, CosmosContainerSettings documentCollection, RequestOptions options = null)
public Task<ResourceResponse<DocumentCollection>> CreateDocumentCollectionAsync(Uri databaseUri, DocumentCollection documentCollection, RequestOptions options = null)
{
if (databaseUri == null)
{
@ -58,16 +59,16 @@ namespace Microsoft.Azure.Cosmos
/// Creates(if doesn't exist) or gets(if already exists) a collection as an asychronous operation in the Azure Cosmos DB service.
/// </summary>
/// <param name="databaseUri">the URI of the database to create the collection in.</param>
/// <param name="documentCollection">The <see cref="CosmosContainerSettings"/> object.</param>
/// <param name="documentCollection">The <see cref="DocumentCollection"/> object.</param>
/// <param name="options">(Optional) Any <see cref="Microsoft.Azure.Cosmos.RequestOptions"/> you wish to provide when creating a Collection. E.g. RequestOptions.OfferThroughput = 400. </param>
/// <returns>The <see cref="CosmosContainerSettings"/> that was created contained within a <see cref="System.Threading.Tasks.Task"/> object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosContainerSettings>> CreateDocumentCollectionIfNotExistsAsync(Uri databaseUri, CosmosContainerSettings documentCollection, RequestOptions options = null)
/// <returns>The <see cref="DocumentCollection"/> that was created contained within a <see cref="System.Threading.Tasks.Task"/> object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<DocumentCollection>> CreateDocumentCollectionIfNotExistsAsync(Uri databaseUri, DocumentCollection documentCollection, RequestOptions options = null)
{
return TaskHelper.InlineIfPossible(() => CreateDocumentCollectionIfNotExistsPrivateAsync(databaseUri, documentCollection, options), null);
}
private async Task<ResourceResponse<CosmosContainerSettings>> CreateDocumentCollectionIfNotExistsPrivateAsync(
Uri databaseUri, CosmosContainerSettings documentCollection, RequestOptions options)
private async Task<ResourceResponse<DocumentCollection>> CreateDocumentCollectionIfNotExistsPrivateAsync(
Uri databaseUri, DocumentCollection documentCollection, RequestOptions options)
{
if (databaseUri == null)
{
@ -116,7 +117,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProcedure">the Microsoft.Azure.Documents.StoredProcedure object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosStoredProcedureSettings>> CreateStoredProcedureAsync(Uri documentCollectionUri, CosmosStoredProcedureSettings storedProcedure, RequestOptions options = null)
public Task<ResourceResponse<StoredProcedure>> CreateStoredProcedureAsync(Uri documentCollectionUri, StoredProcedure storedProcedure, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -132,7 +133,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="trigger">the Microsoft.Azure.Documents.Trigger object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosTriggerSettings>> CreateTriggerAsync(Uri documentCollectionUri, CosmosTriggerSettings trigger, RequestOptions options = null)
public Task<ResourceResponse<Trigger>> CreateTriggerAsync(Uri documentCollectionUri, Trigger trigger, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -148,7 +149,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="function">the Microsoft.Azure.Documents.UserDefinedFunction object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosUserDefinedFunctionSettings>> CreateUserDefinedFunctionAsync(Uri documentCollectionUri, CosmosUserDefinedFunctionSettings function, RequestOptions options = null)
public Task<ResourceResponse<UserDefinedFunction>> CreateUserDefinedFunctionAsync(Uri documentCollectionUri, UserDefinedFunction function, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -202,7 +203,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProcedure">the Microsoft.Azure.Documents.StoredProcedure object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosStoredProcedureSettings>> UpsertStoredProcedureAsync(Uri documentCollectionUri, CosmosStoredProcedureSettings storedProcedure, RequestOptions options = null)
public Task<ResourceResponse<StoredProcedure>> UpsertStoredProcedureAsync(Uri documentCollectionUri, StoredProcedure storedProcedure, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -218,7 +219,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="trigger">the Microsoft.Azure.Documents.Trigger object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosTriggerSettings>> UpsertTriggerAsync(Uri documentCollectionUri, CosmosTriggerSettings trigger, RequestOptions options = null)
public Task<ResourceResponse<Trigger>> UpsertTriggerAsync(Uri documentCollectionUri, Trigger trigger, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -234,7 +235,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="function">the Microsoft.Azure.Documents.UserDefinedFunction object.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosUserDefinedFunctionSettings>> UpsertUserDefinedFunctionAsync(Uri documentCollectionUri, CosmosUserDefinedFunctionSettings function, RequestOptions options = null)
public Task<ResourceResponse<UserDefinedFunction>> UpsertUserDefinedFunctionAsync(Uri documentCollectionUri, UserDefinedFunction function, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -267,7 +268,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="databaseUri">the URI of the database to delete.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosDatabaseSettings>> DeleteDatabaseAsync(Uri databaseUri, RequestOptions options = null)
public Task<ResourceResponse<Database>> DeleteDatabaseAsync(Uri databaseUri, RequestOptions options = null)
{
if (databaseUri == null)
{
@ -298,7 +299,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="documentCollectionUri">the URI of the document collection to delete.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosContainerSettings>> DeleteDocumentCollectionAsync(Uri documentCollectionUri, RequestOptions options = null)
public Task<ResourceResponse<DocumentCollection>> DeleteDocumentCollectionAsync(Uri documentCollectionUri, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -313,7 +314,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProcedureUri">the URI of the stored procedure to delete.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosStoredProcedureSettings>> DeleteStoredProcedureAsync(Uri storedProcedureUri, RequestOptions options = null)
public Task<ResourceResponse<StoredProcedure>> DeleteStoredProcedureAsync(Uri storedProcedureUri, RequestOptions options = null)
{
if (storedProcedureUri == null)
{
@ -329,7 +330,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="triggerUri">the URI of the trigger to delete.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosTriggerSettings>> DeleteTriggerAsync(Uri triggerUri, RequestOptions options = null)
public Task<ResourceResponse<Trigger>> DeleteTriggerAsync(Uri triggerUri, RequestOptions options = null)
{
if (triggerUri == null)
{
@ -344,7 +345,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="functionUri">the URI of the user defined function to delete.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosUserDefinedFunctionSettings>> DeleteUserDefinedFunctionAsync(Uri functionUri, RequestOptions options = null)
public Task<ResourceResponse<UserDefinedFunction>> DeleteUserDefinedFunctionAsync(Uri functionUri, RequestOptions options = null)
{
if (functionUri == null)
{
@ -394,7 +395,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="documentCollection">the updated document collection.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosContainerSettings>> ReplaceDocumentCollectionAsync(Uri documentCollectionUri, CosmosContainerSettings documentCollection, RequestOptions options = null)
public Task<ResourceResponse<DocumentCollection>> ReplaceDocumentCollectionAsync(Uri documentCollectionUri, DocumentCollection documentCollection, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -416,7 +417,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProcedure">the updated stored procedure.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosStoredProcedureSettings>> ReplaceStoredProcedureAsync(Uri storedProcedureUri, CosmosStoredProcedureSettings storedProcedure, RequestOptions options = null)
public Task<ResourceResponse<StoredProcedure>> ReplaceStoredProcedureAsync(Uri storedProcedureUri, StoredProcedure storedProcedure, RequestOptions options = null)
{
if (storedProcedureUri == null)
{
@ -438,7 +439,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="trigger">the updated trigger.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosTriggerSettings>> ReplaceTriggerAsync(Uri triggerUri, CosmosTriggerSettings trigger, RequestOptions options = null)
public Task<ResourceResponse<Trigger>> ReplaceTriggerAsync(Uri triggerUri, Trigger trigger, RequestOptions options = null)
{
if (triggerUri == null)
{
@ -456,7 +457,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="function">the updated user defined function.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<ResourceResponse<CosmosUserDefinedFunctionSettings>> ReplaceUserDefinedFunctionAsync(Uri userDefinedFunctionUri, CosmosUserDefinedFunctionSettings function, RequestOptions options = null)
public Task<ResourceResponse<UserDefinedFunction>> ReplaceUserDefinedFunctionAsync(Uri userDefinedFunctionUri, UserDefinedFunction function, RequestOptions options = null)
{
if (userDefinedFunctionUri == null)
{
@ -488,12 +489,12 @@ namespace Microsoft.Azure.Cosmos
#region Read operation
/// <summary>
/// Reads a <see cref="CosmosDatabaseSettings"/> as an asynchronous operation from the Azure Cosmos DB service.
/// Reads a <see cref="Database"/> as an asynchronous operation from the Azure Cosmos DB service.
/// </summary>
/// <param name="databaseUri">A URI to the Database resource to be read.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="CosmosDatabaseSettings"/> containing the read resource record.
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="Database"/> containing the read resource record.
/// </returns>
/// <exception cref="ArgumentNullException">If <paramref name="databaseUri"/> is not set.</exception>
/// <exception cref="DocumentClientException">This exception can encapsulate many different types of errors. To determine the specific error always look at the StatusCode property. Some common codes you may get when creating a Document are:
@ -524,11 +525,11 @@ namespace Microsoft.Azure.Cosmos
/// Doing a read of a resource is the most efficient way to get a resource from the service. If you know the resource's ID, do a read instead of a query by ID.
/// </para>
/// </remarks>
/// <seealso cref="CosmosDatabaseSettings"/>
/// <seealso cref="Database"/>
/// <seealso cref="Microsoft.Azure.Cosmos.RequestOptions"/>
/// <seealso cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/>
/// <seealso cref="System.Threading.Tasks.Task"/>
public Task<ResourceResponse<CosmosDatabaseSettings>> ReadDatabaseAsync(Uri databaseUri, RequestOptions options = null)
public Task<ResourceResponse<Database>> ReadDatabaseAsync(Uri databaseUri, RequestOptions options = null)
{
if (databaseUri == null)
{
@ -644,12 +645,12 @@ namespace Microsoft.Azure.Cosmos
}
/// <summary>
/// Reads a <see cref="CosmosContainerSettings"/> as an asynchronous operation from the Azure Cosmos DB service.
/// Reads a <see cref="DocumentCollection"/> as an asynchronous operation from the Azure Cosmos DB service.
/// </summary>
/// <param name="documentCollectionUri">A URI to the DocumentCollection resource to be read.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="CosmosContainerSettings"/> containing the read resource record.
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="DocumentCollection"/> containing the read resource record.
/// </returns>
/// <exception cref="ArgumentNullException">If <paramref name="documentCollectionUri"/> is not set.</exception>
/// <exception cref="DocumentClientException">This exception can encapsulate many different types of errors. To determine the specific error always look at the StatusCode property. Some common codes you may get when creating a Document are:
@ -681,11 +682,11 @@ namespace Microsoft.Azure.Cosmos
/// Doing a read of a resource is the most efficient way to get a resource from the service. If you know the resource's ID, do a read instead of a query by ID.
/// </para>
/// </remarks>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="DocumentCollection"/>
/// <seealso cref="Microsoft.Azure.Cosmos.RequestOptions"/>
/// <seealso cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/>
/// <seealso cref="System.Threading.Tasks.Task"/>
public Task<ResourceResponse<CosmosContainerSettings>> ReadDocumentCollectionAsync(Uri documentCollectionUri, RequestOptions options = null)
public Task<ResourceResponse<DocumentCollection>> ReadDocumentCollectionAsync(Uri documentCollectionUri, RequestOptions options = null)
{
if (documentCollectionUri == null)
{
@ -695,12 +696,12 @@ namespace Microsoft.Azure.Cosmos
}
/// <summary>
/// Reads a <see cref="CosmosStoredProcedureSettings"/> as an asynchronous operation from the Azure Cosmos DB service.
/// Reads a <see cref="StoredProcedure"/> as an asynchronous operation from the Azure Cosmos DB service.
/// </summary>
/// <param name="storedProcedureUri">A URI to the StoredProcedure resource to be read.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="CosmosStoredProcedureSettings"/> containing the read resource record.
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="StoredProcedure"/> containing the read resource record.
/// </returns>
/// <exception cref="ArgumentNullException">If <paramref name="storedProcedureUri"/> is not set.</exception>
/// <exception cref="DocumentClientException">This exception can encapsulate many different types of errors. To determine the specific error always look at the StatusCode property. Some common codes you may get when creating a Document are:
@ -733,11 +734,11 @@ namespace Microsoft.Azure.Cosmos
/// Doing a read of a resource is the most efficient way to get a resource from the service. If you know the resource's ID, do a read instead of a query by ID.
/// </para>
/// </remarks>
/// <seealso cref="CosmosStoredProcedureSettings"/>
/// <seealso cref="StoredProcedure"/>
/// <seealso cref="Microsoft.Azure.Cosmos.RequestOptions"/>
/// <seealso cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/>
/// <seealso cref="System.Threading.Tasks.Task"/>
public Task<ResourceResponse<CosmosStoredProcedureSettings>> ReadStoredProcedureAsync(Uri storedProcedureUri, RequestOptions options = null)
public Task<ResourceResponse<StoredProcedure>> ReadStoredProcedureAsync(Uri storedProcedureUri, RequestOptions options = null)
{
if (storedProcedureUri == null)
{
@ -747,12 +748,12 @@ namespace Microsoft.Azure.Cosmos
}
/// <summary>
/// Reads a <see cref="CosmosTriggerSettings"/> as an asynchronous operation from the Azure Cosmos DB service.
/// Reads a <see cref="Trigger"/> as an asynchronous operation from the Azure Cosmos DB service.
/// </summary>
/// <param name="triggerUri">A URI to the Trigger resource to be read.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="CosmosTriggerSettings"/> containing the read resource record.
/// A <see cref="System.Threading.Tasks"/> containing a <see cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/> which wraps a <see cref="Trigger"/> containing the read resource record.
/// </returns>
/// <exception cref="ArgumentNullException">If <paramref name="triggerUri"/> is not set.</exception>
/// <exception cref="DocumentClientException">This exception can encapsulate many different types of errors. To determine the specific error always look at the StatusCode property. Some common codes you may get when creating a Document are:
@ -785,11 +786,11 @@ namespace Microsoft.Azure.Cosmos
/// Doing a read of a resource is the most efficient way to get a resource from the service. If you know the resource's ID, do a read instead of a query by ID.
/// </para>
/// </remarks>
/// <seealso cref="CosmosTriggerSettings"/>
/// <seealso cref="Trigger"/>
/// <seealso cref="Microsoft.Azure.Cosmos.RequestOptions"/>
/// <seealso cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/>
/// <seealso cref="System.Threading.Tasks.Task"/>
public Task<ResourceResponse<CosmosTriggerSettings>> ReadTriggerAsync(Uri triggerUri, RequestOptions options = null)
public Task<ResourceResponse<Trigger>> ReadTriggerAsync(Uri triggerUri, RequestOptions options = null)
{
if (triggerUri == null)
{
@ -799,7 +800,7 @@ namespace Microsoft.Azure.Cosmos
}
/// <summary>
/// Reads a <see cref="CosmosUserDefinedFunctionSettings"/> as an asynchronous operation from the Azure Cosmos DB service.
/// Reads a <see cref="UserDefinedFunction"/> as an asynchronous operation from the Azure Cosmos DB service.
/// </summary>
/// <param name="functionUri">A URI to the User Defined Function resource to be read.</param>
/// <param name="options">The request options for the request.</param>
@ -837,11 +838,11 @@ namespace Microsoft.Azure.Cosmos
/// Doing a read of a resource is the most efficient way to get a resource from the service. If you know the resource's ID, do a read instead of a query by ID.
/// </para>
/// </remarks>
/// <seealso cref="CosmosUserDefinedFunctionSettings"/>
/// <seealso cref="UserDefinedFunction"/>
/// <seealso cref="Microsoft.Azure.Cosmos.RequestOptions"/>
/// <seealso cref="Microsoft.Azure.Cosmos.ResourceResponse{T}"/>
/// <seealso cref="System.Threading.Tasks.Task"/>
public Task<ResourceResponse<CosmosUserDefinedFunctionSettings>> ReadUserDefinedFunctionAsync(Uri functionUri, RequestOptions options = null)
public Task<ResourceResponse<UserDefinedFunction>> ReadUserDefinedFunctionAsync(Uri functionUri, RequestOptions options = null)
{
if (functionUri == null)
{
@ -1014,7 +1015,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="documentCollectionsUri">the URI for the document collections.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<FeedResponse<CosmosContainerSettings>> ReadDocumentCollectionFeedAsync(Uri documentCollectionsUri, FeedOptions options = null)
public Task<FeedResponse<DocumentCollection>> ReadDocumentCollectionFeedAsync(Uri documentCollectionsUri, FeedOptions options = null)
{
if (documentCollectionsUri == null)
{
@ -1029,7 +1030,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProceduresUri">the URI for the stored procedures.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<FeedResponse<CosmosStoredProcedureSettings>> ReadStoredProcedureFeedAsync(Uri storedProceduresUri, FeedOptions options = null)
public Task<FeedResponse<StoredProcedure>> ReadStoredProcedureFeedAsync(Uri storedProceduresUri, FeedOptions options = null)
{
if (storedProceduresUri == null)
{
@ -1044,7 +1045,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="triggersUri">the URI for the triggers.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<FeedResponse<CosmosTriggerSettings>> ReadTriggerFeedAsync(Uri triggersUri, FeedOptions options = null)
public Task<FeedResponse<Trigger>> ReadTriggerFeedAsync(Uri triggersUri, FeedOptions options = null)
{
if (triggersUri == null)
{
@ -1059,7 +1060,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="userDefinedFunctionsUri">the URI for the user defined functions.</param>
/// <param name="options">The request options for the request.</param>
/// <returns>The task object representing the service response for the asynchronous operation.</returns>
public Task<FeedResponse<CosmosUserDefinedFunctionSettings>> ReadUserDefinedFunctionFeedAsync(Uri userDefinedFunctionsUri, FeedOptions options = null)
public Task<FeedResponse<UserDefinedFunction>> ReadUserDefinedFunctionFeedAsync(Uri userDefinedFunctionsUri, FeedOptions options = null)
{
if (userDefinedFunctionsUri == null)
{
@ -1234,7 +1235,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="databaseUri">the URI to the database.</param>
/// <param name="feedOptions">The options for processing the query results feed.</param>
/// <returns>The query result set.</returns>
public IOrderedQueryable<CosmosContainerSettings> CreateDocumentCollectionQuery(Uri databaseUri, FeedOptions feedOptions = null)
public IOrderedQueryable<DocumentCollection> CreateDocumentCollectionQuery(Uri databaseUri, FeedOptions feedOptions = null)
{
if (databaseUri == null)
{
@ -1282,7 +1283,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="databaseUri">Specifies the database to read collections from.</param>
/// <param name="feedOptions">Specifies the options for processing the query results feed.</param>
/// <returns>the query result set.</returns>
internal IDocumentQuery<CosmosContainerSettings> CreateDocumentCollectionChangeFeedQuery(Uri databaseUri, ChangeFeedOptions feedOptions)
internal IDocumentQuery<DocumentCollection> CreateDocumentCollectionChangeFeedQuery(Uri databaseUri, ChangeFeedOptions feedOptions)
{
if(databaseUri == null)
{
@ -1298,7 +1299,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="storedProceduresUri">the URI to the stored procedures.</param>
/// <param name="feedOptions">The options for processing the query results feed.</param>
/// <returns>The query result set.</returns>
public IOrderedQueryable<CosmosStoredProcedureSettings> CreateStoredProcedureQuery(Uri storedProceduresUri, FeedOptions feedOptions = null)
public IOrderedQueryable<StoredProcedure> CreateStoredProcedureQuery(Uri storedProceduresUri, FeedOptions feedOptions = null)
{
if (storedProceduresUri == null)
{
@ -1345,7 +1346,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="triggersUri">the URI to the triggers.</param>
/// <param name="feedOptions">The options for processing the query results feed.</param>
/// <returns>The query result set.</returns>
public IOrderedQueryable<CosmosTriggerSettings> CreateTriggerQuery(Uri triggersUri, FeedOptions feedOptions = null)
public IOrderedQueryable<Trigger> CreateTriggerQuery(Uri triggersUri, FeedOptions feedOptions = null)
{
if (triggersUri == null)
{
@ -1392,7 +1393,7 @@ namespace Microsoft.Azure.Cosmos
/// <param name="userDefinedFunctionsUri">the URI to the user-defined functions.</param>
/// <param name="feedOptions">The options for processing the query results feed.</param>
/// <returns>The query result set.</returns>
public IOrderedQueryable<CosmosUserDefinedFunctionSettings> CreateUserDefinedFunctionQuery(Uri userDefinedFunctionsUri, FeedOptions feedOptions = null)
public IOrderedQueryable<UserDefinedFunction> CreateUserDefinedFunctionQuery(Uri userDefinedFunctionsUri, FeedOptions feedOptions = null)
{
if (userDefinedFunctionsUri == null)
{

Просмотреть файл

@ -1,89 +0,0 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using Newtonsoft.Json;
using Microsoft.Azure.Cosmos.Internal;
/// <summary>
/// Represents the template class used by methods returning single objects in the Azure Cosmos DB service.
/// </summary>
/// <typeparam name="TDocument">the document type.</typeparam>
/// <remarks>
/// Response from type-specific read of Document resource(ReadDocumentAsync{TDocument}) returns the response wrapped in a
/// DocumentResponse object. This contains the metadata from the response headers from the Azure Cosmos DB call including
/// the request units (RequestCharge), activity ID, quotas/usage of resources and the typed document object(TDocument).
/// </remarks>
/// <example>
/// The following example extracts the CustomerName property, request units consumed, activity ID and StatusCode from a ReadDocumentAsync{Customer} call.
/// <code language="c#">
/// <![CDATA[
/// DocumentResponse<Customer> response = await client.ReadDocumentAsync<Customer>(documentLink);
/// Console.WriteLine(response.Document.CustomerName);
/// Console.WriteLine(response.RequestCharge);
/// Console.WriteLine(response.ActivityId);
/// Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201
/// ]]>
/// </code>
/// </example>
internal sealed class DocumentResponse<TDocument> : ResourceResponseBase, IDocumentResponse<TDocument>
{
private TDocument document;
private JsonSerializerSettings settings;
/// <summary>
/// Constructor exposed for mocking purposes for the Azure Cosmos DB service.
/// </summary>
public DocumentResponse()
{
}
/// <summary>
/// Constructor exposed for mocking purposes for the Azure Cosmos DB service.
/// </summary>
/// <param name="document"></param>
public DocumentResponse(TDocument document)
:this()
{
this.document = document;
}
internal DocumentResponse(DocumentServiceResponse response, JsonSerializerSettings settings = null)
:base(response)
{
this.settings = settings;
}
/// <summary>
/// Gets the document returned in the response from the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The document returned in the response.
/// </value>
public TDocument Document
{
get
{
if (this.document == null)
{
Document doc = this.response.GetResource<Document>();
doc.SerializerSettings = this.settings;
this.document = (TDocument)(dynamic)doc;
}
return this.document;
}
}
/// <summary>
/// Returns the document in the response implicitly from the Azure Cosmos DB service.
/// </summary>
/// <param name="source">The DocumentResponse source.</param>
/// <returns>The document object.</returns>
public static implicit operator TDocument(DocumentResponse<TDocument> source)
{
return source.Document;
}
}
}

Просмотреть файл

@ -1,405 +1,406 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Azure.Cosmos.Internal;
using Newtonsoft.Json;
/// <summary>
/// Specifies the options associated with feed methods (enumeration operations) in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// Used to manage query and ReadFeed execution. Can use FeedOptions to set page size (MaxItemCount)
/// </remarks>
internal sealed class FeedOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="FeedOptions"/> class for the Azure Cosmos DB service.
/// </summary>
public FeedOptions()
{
}
internal FeedOptions(FeedOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
this.MaxItemCount = options.MaxItemCount;
this.RequestContinuation = options.RequestContinuation;
this.SessionToken = options.SessionToken;
this.EnableScanInQuery = options.EnableScanInQuery;
this.EnableCrossPartitionQuery = options.EnableCrossPartitionQuery;
this.EnableLowPrecisionOrderBy = options.EnableLowPrecisionOrderBy;
this.MaxBufferedItemCount = options.MaxBufferedItemCount;
this.MaxDegreeOfParallelism = options.MaxDegreeOfParallelism;
this.PartitionKeyRangeId = options.PartitionKeyRangeId;
this.PopulateQueryMetrics = options.PopulateQueryMetrics;
this.ResponseContinuationTokenLimitInKb = options.ResponseContinuationTokenLimitInKb;
if (options.PartitionKey == null)
{
this.PartitionKey = null;
}
else
{
this.PartitionKey = PartitionKey.FromInternalKey(options.PartitionKey.InternalKey);
}
this.EmitVerboseTracesInQuery = options.EmitVerboseTracesInQuery;
this.FilterBySchemaResourceId = options.FilterBySchemaResourceId;
this.RequestContinuation = options.RequestContinuation;
this.ConsistencyLevel = options.ConsistencyLevel;
this.JsonSerializerSettings = options.JsonSerializerSettings;
this.ForceQueryScan = options.ForceQueryScan;
this.EnumerationDirection = options.EnumerationDirection;
this.ReadFeedKeyType = options.ReadFeedKeyType;
this.StartId = options.StartId;
this.EndId = options.EndId;
this.StartEpk = options.StartEpk;
this.EndEpk = options.EndEpk;
this.ContentSerializationFormat = options.ContentSerializationFormat;
this.CosmosSerializationOptions = options.CosmosSerializationOptions;
this.Properties = options.Properties;
}
/// <summary>
/// Gets or sets the maximum number of items to be returned in the enumeration operation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The maximum number of items to be returned in the enumeration operation.
/// </value>
/// <remarks>
/// Used for query pagination.
/// '-1' Used for dynamic page size.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Fetch query results 10 at a time.
/// using (var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions { MaxItemCount = 10 }))
/// {
/// while (queryable.HasResults)
/// {
/// FeedResponse<Book> response = await queryable.ExecuteNext<Book>();
/// }
/// }
/// ]]>
/// </code>
/// </example>
public int? MaxItemCount { get; set; }
/// <summary>
/// Gets or sets the request continuation token in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The request continuation token.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Resume query execution using the continuation from the previous query
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions { RequestContinuation = prevQuery.ResponseContinuation });
/// ]]>
/// </code>
/// </example>
public string RequestContinuation { get; set; }
/// <summary>
/// Gets or sets the session token for use with session consistency in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The session token for use with session consistency.
/// </value>
/// <remarks>
/// Useful for applications that are load balanced across multiple Microsoft.Azure.Documents.Client.DocumentClient instances.
/// In this case, round-trip the token from end user to the application and then back to Azure Cosmos DB so that a session
/// can be preserved across servers.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { SessionToken = lastSessionToken });
/// ]]>
/// </code>
/// </example>
public string SessionToken { get; set; }
/// <summary>
/// Gets or sets the option to enable scans on the queries which couldn't be served
/// as indexing was opted out on the requested paths in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// Option is true if scan on queries is enabled; otherwise, false.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Enable scan when Range index is not specified.
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { EnableScanInQuery = true }).Where(b => b.Price > 1000);
/// ]]>
/// </code>
/// </example>
public bool? EnableScanInQuery { get; set; }
/// <summary>
/// Gets or sets a value indicating whether users are enabled to send more than one request to execute
/// the query in the Azure Cosmos DB service. More than one request is necessary if the query
/// is not scoped to single partition key value.
/// </summary>
/// <value>
/// Option is true if cross-partition query execution is enabled; otherwise, false.
/// </value>
/// <remarks>
/// <para>
/// This option only applies to queries on documents and document attachments.
/// </para>
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Enable cross partition query.
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { EnableCrossPartitionQuery = true }).Where(b => b.Price > 1000);
/// ]]>
/// </code>
/// </example>
public bool EnableCrossPartitionQuery { get; set; }
/// <summary>
/// Gets or sets the option to enable low precision order by in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The option to enable low-precision order by.
/// </value>
public bool? EnableLowPrecisionOrderBy { get; set; }
/// <summary>
/// Gets or sets the <see cref="PartitionKey"/> for the current request in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// Partition key is required when read documents or attachments feed in a partitioned collection.
/// Specifically Partition key is required for :
/// <see cref="DocumentClient.ReadDocumentFeedAsync(string, FeedOptions, CancellationToken)"/> and
/// <see cref="DocumentClient.ReadConflictFeedAsync(string, FeedOptions)"/>.
/// Only documents in partitions containing the <see cref="PartitionKey"/> is returned in the result.
/// </para>
/// </remarks>
/// <example>
/// The following example shows how to read a document feed in a partitioned collection using <see cref="PartitionKey"/>.
/// The example assumes the collection is created with a <see cref="PartitionKeyDefinition"/> on the 'country' property in all the documents.
/// <code language="c#">
/// <![CDATA[
/// await client.ReadDocumentFeedAsync(
/// collection.SelfLink,
/// new RequestOptions { PartitionKey = new PartitionKey("USA") } );
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="Microsoft.Azure.Cosmos.PartitionKeyDefinition"/>
public PartitionKey PartitionKey { get; set; }
/// <summary>
/// Gets or sets the partition key range id for the current request.
/// </summary>
/// <remarks>
/// <para>
/// ReadFeed requests can use this to forward request to specific range.
/// This is usefull in case of bulk export scenarios.
/// </para>
/// </remarks>
/// <example>
/// The following example shows how to read a document feed in a partitioned collection from partition key range "20".
/// <code language="c#">
/// <![CDATA[
/// await client.ReadDocumentFeedAsync(
/// collection.SelfLink,
/// new RequestOptions { PartitionKeyRangeId = "20" } );
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosContainerSettings"/>
public string PartitionKeyRangeId { get; set; }
/// <summary>
/// Gets or sets the number of concurrent operations run client side during
/// parallel query execution in the Azure Cosmos DB service.
/// A positive property value limits the number of
/// concurrent operations to the set value. If it is set to less than 0, the
/// system automatically decides the number of concurrent operations to run.
/// </summary>
/// <value>
/// The maximum number of concurrent operations during parallel execution. Defaults to 0.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions {
/// MaxDegreeOfParallelism = 5});
/// ]]>
/// </code>
/// </example>
public int MaxDegreeOfParallelism { get; set; }
/// <summary>
/// Gets or sets the maximum number of items that can be buffered client side during
/// parallel query execution in the Azure Cosmos DB service.
/// A positive property value limits the number of buffered
/// items to the set value. If it is set to less than 0, the system automatically
/// decides the number of items to buffer.
/// </summary>
/// <value>
/// The maximum count of items that can be buffered during parallel query execution.
/// </value>
/// <remarks>
/// This is only suggestive and cannot be abided by in certain cases.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions {
/// MaximumBufferSize = 10, MaxDegreeOfParallelism = 2 });
/// ]]>
/// </code>
/// </example>
public int MaxBufferedItemCount { get; set; }
/// <summary>
/// Gets or sets the option to allow queries to emit out verbose traces
/// for investigation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// Option is true if query tracing is enabled; otherwise, false.
/// </value>
internal bool? EmitVerboseTracesInQuery { get; set; }
/// <summary>
/// Gets or sets the schema rid which could be used to filter the document feed response
/// in order to focus on the documents for a particular schema.
/// </summary>
/// <value>
/// By default, it is <c>null</c> which means no filtering will be applied.
/// Otherwise, it must be a valid resource id of Schema resource.
/// </value>
internal string FilterBySchemaResourceId { get; set; }
/// <summary>
/// Gets or sets the <see cref="PopulateQueryMetrics"/> request option for document query requests in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// PopulateQueryMetrics is used to enable/disable getting metrics relating to query execution on document query requests.
/// </para>
/// </remarks>
public bool PopulateQueryMetrics { get; set; }
/// <summary>
/// Gets or sets the <see cref="ResponseContinuationTokenLimitInKb"/> request option for document query requests in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// ResponseContinuationTokenLimitInKb is used to limit the length of continuation token in the query response. Valid values are >= 0.
/// </para>
/// </remarks>
public int? ResponseContinuationTokenLimitInKb { get; set; }
/// <summary>
/// Gets or sets the <see cref="JsonSerializerSettings"/> for the current request used to deserialize the document.
/// If null, uses the default serializer settings set up in the DocumentClient.
/// </summary>
public JsonSerializerSettings JsonSerializerSettings { get; set; }
/// <summary>
/// Gets or sets the consistency level required for the feed (query/read feed) operation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The consistency level required for the request.
/// </value>
/// <remarks>
/// Azure Cosmos DB offers 5 different consistency levels. Strong, Bounded Staleness, Session, Consistent Prefix and Eventual - in order of strongest to weakest consistency. <see cref="ConnectionPolicy"/>
///
/// Azure Cosmos query/DB feed operations may be retrieved from many partitions, each accessed across many round trips. The consistency level is honored only within a partition and round trip.
/// <para>
/// While this is set at a database account level, Azure Cosmos DB allows a developer to override the default consistency level
/// for each individual request.
/// </para>
/// </remarks>
/// <example>
/// This example uses FeedOptions to override the consistency level to Eventual.
/// <code language="c#">
/// <![CDATA[
/// Document doc = client.ReadDocumentFeedAsync(documentLink, new FeedOptions { ConsistencyLevel = ConsistencyLevel.Eventual });
/// ]]>
/// </code>
/// </example>
/// <seealso cref="ConsistencyLevel"/>
public ConsistencyLevel? ConsistencyLevel { get; set; }
/// <summary>
/// Gets or sets the flag that tells the backend to forces the query to perform a scan (at a request level).
/// </summary>
internal bool ForceQueryScan { get; set; }
/// <summary>
/// Gets or sets the EnumerationDirection
/// To be used along with Read feed operation
/// </summary>
internal EnumerationDirection? EnumerationDirection { get; set; }
/// <summary>
/// Gets or sets the ReadFeedKeyType
/// To be used along with Read feed operation
/// </summary>
internal ReadFeedKeyType? ReadFeedKeyType { get; set; }
/// <summary>
/// Gets or sets the StartId
/// To be used along with Read feed operation
/// </summary>
internal string StartId { get; set; }
/// <summary>
/// Gets or sets the EndId
/// To be used along with Read feed operation
/// </summary>
internal string EndId { get; set; }
/// <summary>
/// Gets or sets the StartEpk
/// To be used along with Read feed operation
/// </summary>
internal string StartEpk { get; set; }
/// <summary>
/// Gets or sets the EndEpk
/// To be used along with Read feed operation
/// </summary>
internal string EndEpk { get; set; }
/// <summary>
/// Gets or sets the ContentSerializationFormat for the feed (query/read feed) operation in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// If the document is stored in a different serialization format then the one requested, then there will be a rewrite over the wire, but the source document will be untouched.
/// </remarks>
internal ContentSerializationFormat? ContentSerializationFormat { get; set; }
/// <summary>
/// Gets or sets the custom serialization options for query
/// </summary>
internal CosmosSerializationOptions CosmosSerializationOptions { get; set; }
internal IDictionary<string, object> Properties { get; set; }
}
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
/// <summary>
/// Specifies the options associated with feed methods (enumeration operations) in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// Used to manage query and ReadFeed execution. Can use FeedOptions to set page size (MaxItemCount)
/// </remarks>
internal sealed class FeedOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="FeedOptions"/> class for the Azure Cosmos DB service.
/// </summary>
public FeedOptions()
{
}
internal FeedOptions(FeedOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
this.MaxItemCount = options.MaxItemCount;
this.RequestContinuation = options.RequestContinuation;
this.SessionToken = options.SessionToken;
this.EnableScanInQuery = options.EnableScanInQuery;
this.EnableCrossPartitionQuery = options.EnableCrossPartitionQuery;
this.EnableLowPrecisionOrderBy = options.EnableLowPrecisionOrderBy;
this.MaxBufferedItemCount = options.MaxBufferedItemCount;
this.MaxDegreeOfParallelism = options.MaxDegreeOfParallelism;
this.PartitionKeyRangeId = options.PartitionKeyRangeId;
this.PopulateQueryMetrics = options.PopulateQueryMetrics;
this.ResponseContinuationTokenLimitInKb = options.ResponseContinuationTokenLimitInKb;
if (options.PartitionKey == null)
{
this.PartitionKey = null;
}
else
{
this.PartitionKey = PartitionKey.FromInternalKey(options.PartitionKey.InternalKey);
}
this.EmitVerboseTracesInQuery = options.EmitVerboseTracesInQuery;
this.FilterBySchemaResourceId = options.FilterBySchemaResourceId;
this.RequestContinuation = options.RequestContinuation;
this.ConsistencyLevel = options.ConsistencyLevel;
this.JsonSerializerSettings = options.JsonSerializerSettings;
this.ForceQueryScan = options.ForceQueryScan;
this.EnumerationDirection = options.EnumerationDirection;
this.ReadFeedKeyType = options.ReadFeedKeyType;
this.StartId = options.StartId;
this.EndId = options.EndId;
this.StartEpk = options.StartEpk;
this.EndEpk = options.EndEpk;
this.ContentSerializationFormat = options.ContentSerializationFormat;
this.CosmosSerializationOptions = options.CosmosSerializationOptions;
this.Properties = options.Properties;
}
/// <summary>
/// Gets or sets the maximum number of items to be returned in the enumeration operation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The maximum number of items to be returned in the enumeration operation.
/// </value>
/// <remarks>
/// Used for query pagination.
/// '-1' Used for dynamic page size.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Fetch query results 10 at a time.
/// using (var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions { MaxItemCount = 10 }))
/// {
/// while (queryable.HasResults)
/// {
/// FeedResponse<Book> response = await queryable.ExecuteNext<Book>();
/// }
/// }
/// ]]>
/// </code>
/// </example>
public int? MaxItemCount { get; set; }
/// <summary>
/// Gets or sets the request continuation token in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The request continuation token.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Resume query execution using the continuation from the previous query
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions { RequestContinuation = prevQuery.ResponseContinuation });
/// ]]>
/// </code>
/// </example>
public string RequestContinuation { get; set; }
/// <summary>
/// Gets or sets the session token for use with session consistency in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The session token for use with session consistency.
/// </value>
/// <remarks>
/// Useful for applications that are load balanced across multiple Microsoft.Azure.Documents.Client.DocumentClient instances.
/// In this case, round-trip the token from end user to the application and then back to Azure Cosmos DB so that a session
/// can be preserved across servers.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { SessionToken = lastSessionToken });
/// ]]>
/// </code>
/// </example>
public string SessionToken { get; set; }
/// <summary>
/// Gets or sets the option to enable scans on the queries which couldn't be served
/// as indexing was opted out on the requested paths in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// Option is true if scan on queries is enabled; otherwise, false.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Enable scan when Range index is not specified.
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { EnableScanInQuery = true }).Where(b => b.Price > 1000);
/// ]]>
/// </code>
/// </example>
public bool? EnableScanInQuery { get; set; }
/// <summary>
/// Gets or sets a value indicating whether users are enabled to send more than one request to execute
/// the query in the Azure Cosmos DB service. More than one request is necessary if the query
/// is not scoped to single partition key value.
/// </summary>
/// <value>
/// Option is true if cross-partition query execution is enabled; otherwise, false.
/// </value>
/// <remarks>
/// <para>
/// This option only applies to queries on documents and document attachments.
/// </para>
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// // Enable cross partition query.
/// var queryable = client.CreateDocumentQuery<Book>(
/// collectionLink, new FeedOptions { EnableCrossPartitionQuery = true }).Where(b => b.Price > 1000);
/// ]]>
/// </code>
/// </example>
public bool EnableCrossPartitionQuery { get; set; }
/// <summary>
/// Gets or sets the option to enable low precision order by in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The option to enable low-precision order by.
/// </value>
public bool? EnableLowPrecisionOrderBy { get; set; }
/// <summary>
/// Gets or sets the <see cref="PartitionKey"/> for the current request in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// Partition key is required when read documents or attachments feed in a partitioned collection.
/// Specifically Partition key is required for :
/// <see cref="DocumentClient.ReadDocumentFeedAsync(string, FeedOptions, CancellationToken)"/> and
/// <see cref="DocumentClient.ReadConflictFeedAsync(string, FeedOptions)"/>.
/// Only documents in partitions containing the <see cref="PartitionKey"/> is returned in the result.
/// </para>
/// </remarks>
/// <example>
/// The following example shows how to read a document feed in a partitioned collection using <see cref="PartitionKey"/>.
/// The example assumes the collection is created with a <see cref="PartitionKeyDefinition"/> on the 'country' property in all the documents.
/// <code language="c#">
/// <![CDATA[
/// await client.ReadDocumentFeedAsync(
/// collection.SelfLink,
/// new RequestOptions { PartitionKey = new PartitionKey("USA") } );
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="Microsoft.Azure.Cosmos.PartitionKeyDefinition"/>
public PartitionKey PartitionKey { get; set; }
/// <summary>
/// Gets or sets the partition key range id for the current request.
/// </summary>
/// <remarks>
/// <para>
/// ReadFeed requests can use this to forward request to specific range.
/// This is usefull in case of bulk export scenarios.
/// </para>
/// </remarks>
/// <example>
/// The following example shows how to read a document feed in a partitioned collection from partition key range "20".
/// <code language="c#">
/// <![CDATA[
/// await client.ReadDocumentFeedAsync(
/// collection.SelfLink,
/// new RequestOptions { PartitionKeyRangeId = "20" } );
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosContainerSettings"/>
public string PartitionKeyRangeId { get; set; }
/// <summary>
/// Gets or sets the number of concurrent operations run client side during
/// parallel query execution in the Azure Cosmos DB service.
/// A positive property value limits the number of
/// concurrent operations to the set value. If it is set to less than 0, the
/// system automatically decides the number of concurrent operations to run.
/// </summary>
/// <value>
/// The maximum number of concurrent operations during parallel execution. Defaults to 0.
/// </value>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions {
/// MaxDegreeOfParallelism = 5});
/// ]]>
/// </code>
/// </example>
public int MaxDegreeOfParallelism { get; set; }
/// <summary>
/// Gets or sets the maximum number of items that can be buffered client side during
/// parallel query execution in the Azure Cosmos DB service.
/// A positive property value limits the number of buffered
/// items to the set value. If it is set to less than 0, the system automatically
/// decides the number of items to buffer.
/// </summary>
/// <value>
/// The maximum count of items that can be buffered during parallel query execution.
/// </value>
/// <remarks>
/// This is only suggestive and cannot be abided by in certain cases.
/// </remarks>
/// <example>
/// <code language="c#">
/// <![CDATA[
/// var queryable = client.CreateDocumentQuery<Book>(collectionLink, new FeedOptions {
/// MaximumBufferSize = 10, MaxDegreeOfParallelism = 2 });
/// ]]>
/// </code>
/// </example>
public int MaxBufferedItemCount { get; set; }
/// <summary>
/// Gets or sets the option to allow queries to emit out verbose traces
/// for investigation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// Option is true if query tracing is enabled; otherwise, false.
/// </value>
internal bool? EmitVerboseTracesInQuery { get; set; }
/// <summary>
/// Gets or sets the schema rid which could be used to filter the document feed response
/// in order to focus on the documents for a particular schema.
/// </summary>
/// <value>
/// By default, it is <c>null</c> which means no filtering will be applied.
/// Otherwise, it must be a valid resource id of Schema resource.
/// </value>
internal string FilterBySchemaResourceId { get; set; }
/// <summary>
/// Gets or sets the <see cref="PopulateQueryMetrics"/> request option for document query requests in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// PopulateQueryMetrics is used to enable/disable getting metrics relating to query execution on document query requests.
/// </para>
/// </remarks>
public bool PopulateQueryMetrics { get; set; }
/// <summary>
/// Gets or sets the <see cref="ResponseContinuationTokenLimitInKb"/> request option for document query requests in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// <para>
/// ResponseContinuationTokenLimitInKb is used to limit the length of continuation token in the query response. Valid values are >= 0.
/// </para>
/// </remarks>
public int? ResponseContinuationTokenLimitInKb { get; set; }
/// <summary>
/// Gets or sets the <see cref="JsonSerializerSettings"/> for the current request used to deserialize the document.
/// If null, uses the default serializer settings set up in the DocumentClient.
/// </summary>
public JsonSerializerSettings JsonSerializerSettings { get; set; }
/// <summary>
/// Gets or sets the consistency level required for the feed (query/read feed) operation in the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The consistency level required for the request.
/// </value>
/// <remarks>
/// Azure Cosmos DB offers 5 different consistency levels. Strong, Bounded Staleness, Session, Consistent Prefix and Eventual - in order of strongest to weakest consistency. <see cref="ConnectionPolicy"/>
///
/// Azure Cosmos query/DB feed operations may be retrieved from many partitions, each accessed across many round trips. The consistency level is honored only within a partition and round trip.
/// <para>
/// While this is set at a database account level, Azure Cosmos DB allows a developer to override the default consistency level
/// for each individual request.
/// </para>
/// </remarks>
/// <example>
/// This example uses FeedOptions to override the consistency level to Eventual.
/// <code language="c#">
/// <![CDATA[
/// Document doc = client.ReadDocumentFeedAsync(documentLink, new FeedOptions { ConsistencyLevel = ConsistencyLevel.Eventual });
/// ]]>
/// </code>
/// </example>
/// <seealso cref="ConsistencyLevel"/>
public ConsistencyLevel? ConsistencyLevel { get; set; }
/// <summary>
/// Gets or sets the flag that tells the backend to forces the query to perform a scan (at a request level).
/// </summary>
internal bool ForceQueryScan { get; set; }
/// <summary>
/// Gets or sets the EnumerationDirection
/// To be used along with Read feed operation
/// </summary>
internal EnumerationDirection? EnumerationDirection { get; set; }
/// <summary>
/// Gets or sets the ReadFeedKeyType
/// To be used along with Read feed operation
/// </summary>
internal ReadFeedKeyType? ReadFeedKeyType { get; set; }
/// <summary>
/// Gets or sets the StartId
/// To be used along with Read feed operation
/// </summary>
internal string StartId { get; set; }
/// <summary>
/// Gets or sets the EndId
/// To be used along with Read feed operation
/// </summary>
internal string EndId { get; set; }
/// <summary>
/// Gets or sets the StartEpk
/// To be used along with Read feed operation
/// </summary>
internal string StartEpk { get; set; }
/// <summary>
/// Gets or sets the EndEpk
/// To be used along with Read feed operation
/// </summary>
internal string EndEpk { get; set; }
/// <summary>
/// Gets or sets the ContentSerializationFormat for the feed (query/read feed) operation in the Azure Cosmos DB service.
/// </summary>
/// <remarks>
/// If the document is stored in a different serialization format then the one requested, then there will be a rewrite over the wire, but the source document will be untouched.
/// </remarks>
internal ContentSerializationFormat? ContentSerializationFormat { get; set; }
/// <summary>
/// Gets or sets the custom serialization options for query
/// </summary>
internal CosmosSerializationOptions CosmosSerializationOptions { get; set; }
internal IDictionary<string, object> Properties { get; set; }
}
}

Просмотреть файл

@ -15,6 +15,8 @@ namespace Microsoft.Azure.Cosmos
using System.Reflection;
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
/// <summary>
/// Represents the template class used by feed methods (enumeration operations) for the Azure Cosmos DB service.

Просмотреть файл

@ -9,10 +9,9 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using System.Text;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Json;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using JsonWriter = Json.JsonWriter;
internal static class FeedResponseBinder
@ -80,8 +79,8 @@ namespace Microsoft.Azure.Cosmos
// If the resource type is an offer and the requested type is either a Offer or OfferV2 or dynamic
// create a OfferV2 object and cast it to T. This is a temporary fix until offers is moved to v3 API.
if (resourceType == ResourceType.Offer &&
(typeof(T).IsSubclassOf(typeof(CosmosResource)) || typeof(T) == typeof(object)))
if (resourceType == ResourceType.Offer &&
(typeof(T).IsSubclassOf(typeof(Resource)) || typeof(T) == typeof(object)))
{
typedResults = JsonConvert.DeserializeObject<List<OfferV2>>(jsonText, settings).Cast<T>();
}

Просмотреть файл

@ -11,6 +11,8 @@ namespace Microsoft.Azure.Cosmos
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
internal sealed class GatewayAccountReader
{
@ -78,9 +80,7 @@ namespace Microsoft.Azure.Cosmos
{
using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage))
{
CosmosAccountSettings databaseAccount = documentServiceResponse.GetInternalResource<CosmosAccountSettings>(CosmosAccountSettings.CreateNewInstance);
return databaseAccount;
return CosmosResource.FromStream<CosmosAccountSettings>(documentServiceResponse);
}
}
}

Просмотреть файл

@ -17,6 +17,8 @@ namespace Microsoft.Azure.Cosmos
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Newtonsoft.Json;
// Marking it as non-sealed in order to unit test it using Moq framework
@ -105,7 +107,7 @@ namespace Microsoft.Azure.Cosmos
{
using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage))
{
databaseAccount = documentServiceResponse.GetInternalResource<CosmosAccountSettings>(CosmosAccountSettings.CreateNewInstance);
databaseAccount = CosmosResource.FromStream<CosmosAccountSettings>(documentServiceResponse);
}
long longValue;

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Handlers
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal abstract class AbstractRetryHandler : CosmosRequestHandler
{

Просмотреть файл

@ -14,6 +14,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Common;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Represents a request in the processing pipeline of the Azure Cosmos DB SDK.

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos
using System.Net;
using System.Net.Http;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Represents a response from the Azure Cosmos DB service.

Просмотреть файл

@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Handlers
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Handler to ensure that CollectionCache and PartitionRoutingMap for a given collection exists

Просмотреть файл

@ -14,9 +14,11 @@ namespace Microsoft.Azure.Cosmos.Handlers
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Routing;
using Newtonsoft.Json;
using static Microsoft.Azure.Cosmos.Internal.RntbdConstants;
using static Microsoft.Azure.Cosmos.Routing.PartitionRoutingHelper;
using static Microsoft.Azure.Documents.RntbdConstants;
/// <summary>
/// Handler which manages the continution token and partion-key-range-id selection depending on a provided start and end epk and direction.

Просмотреть файл

@ -5,6 +5,7 @@
namespace Microsoft.Azure.Cosmos.Handlers
{
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using System;
using System.Globalization;
using System.Threading;
@ -39,7 +40,7 @@ namespace Microsoft.Azure.Cosmos.Handlers
// Validate the request consistency compatibility with account consistency
// Type based access context for requested consistency preferred for performance
ConsistencyLevel? consistencyLevel = null;
Cosmos.ConsistencyLevel? consistencyLevel = null;
if (promotedRequestOptions is CosmosItemRequestOptions)
{
consistencyLevel = (promotedRequestOptions as CosmosItemRequestOptions).ConsistencyLevel;

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Handlers
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Handler which selects the piepline for the requested resource operation

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Handlers
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
//TODO: write unit test for this handler
internal class TransportHandler : CosmosRequestHandler

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using System.Reflection;
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Documents.Collections;
/// <summary>
/// Internal header class with priority access for known headers and support for dictionary-based access to other headers.

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using System.Reflection;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Http headers in a <see cref="CosmosRequestMessage"/>.

Просмотреть файл

@ -11,6 +11,7 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using System.Reflection;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// HTTP headers in a <see cref="CosmosResponseMessage"/>.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal interface IRetryPolicyFactory
{

Просмотреть файл

@ -1,23 +0,0 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
/// <summary>
/// Interface exposed for mocking purposes for the Azure Cosmos DB service.
/// </summary>
internal interface IDocumentResponse<TDocument> : IResourceResponseBase
{
/// <summary>
/// Gets the document returned in the response.
/// </summary>
/// <value>
/// The document returned in the response.
/// </value>
/// <remarks>
/// This is exposed for mocking purposes for the Azure Cosmos DB service.
/// </remarks>
TDocument Document { get; }
}
}

Просмотреть файл

@ -4,6 +4,7 @@
namespace Microsoft.Azure.Cosmos
{
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Documents.Collections;
using System;
using System.IO;
using System.Threading.Tasks;

Просмотреть файл

@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Common
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal interface IRequestSigner
{

Просмотреть файл

@ -1,24 +0,0 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
/// <summary>
/// Interface exposed for mocking purposes for the Azure Cosmos DB service.
/// </summary>
/// <typeparam name="TResource">The resource type.</typeparam>
internal interface IResourceResponse<TResource> : IResourceResponseBase where TResource : CosmosResource, new()
{
/// <summary>
/// Gets the resource returned in the response.
/// </summary>
/// <value>
/// The resource returned in the response.
/// </value>
/// <remarks>
/// This is exposed for mocking purposes for the Azure Cosmos DB service.
/// </remarks>
TResource Resource { get; }
}
}

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal sealed class IndexingPolicyBuilder
{

Просмотреть файл

@ -0,0 +1,168 @@
//-----------------------------------------------------------------------
// <copyright file="ByteOrder.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
/// <summary>
/// The ByteOrder class is capable of reversing the bytes of any primitive type.
/// </summary>
internal static class ByteOrder
{
/// <summary>
/// Reverses a single byte.
/// </summary>
/// <param name="value">The byte to reverse</param>
/// <returns>The reversed byte.</returns>
/// <remarks>Since a single byte has no byte order, so the value itself is returned so this is essentially a NO-OP.</remarks>
public static byte Reverse(byte value)
{
return value;
}
/// <summary>
/// Reverses a bool.
/// </summary>
/// <param name="value">The bool to reverse</param>
/// <returns>The reversed bool.</returns>
/// <remarks>Since a bool has no byte order, so the value itself is returned so this is essentially a NO-OP.</remarks>
public static bool Reverse(bool value)
{
return value;
}
/// <summary>
/// Reverses a char.
/// </summary>
/// <param name="value">The char to reverse.</param>
/// <returns>The reversed char.</returns>
public static char Reverse(char value)
{
ushort b1 = (ushort)(((ushort)value >> 0) & 0xff);
ushort b2 = (ushort)(((ushort)value >> 8) & 0xff);
return (char)(b1 << 8 | b2 << 0);
}
/// <summary>
/// Reverses a short.
/// </summary>
/// <param name="value">The short to reverse.</param>
/// <returns>The reversed short.</returns>
public static short Reverse(short value)
{
ushort b1 = (ushort)(((ushort)value >> 0) & 0xff);
ushort b2 = (ushort)(((ushort)value >> 8) & 0xff);
return (short)(b1 << 8 | b2 << 0);
}
/// <summary>
/// Reverses a ushort.
/// </summary>
/// <param name="value">The ushort to reverse.</param>
/// <returns>The reversed ushort.</returns>
public static ushort Reverse(ushort value)
{
ushort b1 = (ushort)((value >> 0) & 0xff);
ushort b2 = (ushort)((value >> 8) & 0xff);
return (ushort)(b1 << 8 | b2 << 0);
}
/// <summary>
/// Reverses a int.
/// </summary>
/// <param name="value">The int to reverse.</param>
/// <returns>The reversed int.</returns>
public static int Reverse(int value)
{
uint b1 = ((uint)value >> 0) & 0xff;
uint b2 = ((uint)value >> 8) & 0xff;
uint b3 = ((uint)value >> 16) & 0xff;
uint b4 = ((uint)value >> 24) & 0xff;
return (int)(b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0);
}
/// <summary>
/// Reverses a uint.
/// </summary>
/// <param name="value">The uint to reverse.</param>
/// <returns>The reversed uint.</returns>
public static uint Reverse(uint value)
{
uint b1 = (value >> 0) & 0xff;
uint b2 = (value >> 8) & 0xff;
uint b3 = (value >> 16) & 0xff;
uint b4 = (value >> 24) & 0xff;
return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
}
/// <summary>
/// Reverses a long.
/// </summary>
/// <param name="value">The long to reverse.</param>
/// <returns>The reversed long.</returns>
public static long Reverse(long value)
{
ulong b1 = ((ulong)value >> 0) & 0xff;
ulong b2 = ((ulong)value >> 8) & 0xff;
ulong b3 = ((ulong)value >> 16) & 0xff;
ulong b4 = ((ulong)value >> 24) & 0xff;
ulong b5 = ((ulong)value >> 32) & 0xff;
ulong b6 = ((ulong)value >> 40) & 0xff;
ulong b7 = ((ulong)value >> 48) & 0xff;
ulong b8 = ((ulong)value >> 56) & 0xff;
return (long)(b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8 << 0);
}
/// <summary>
/// Reverses a ulong.
/// </summary>
/// <param name="value">The ulong to reverse.</param>
/// <returns>The reversed ulong.</returns>
public static ulong Reverse(ulong value)
{
ulong b1 = (value >> 0) & 0xff;
ulong b2 = (value >> 8) & 0xff;
ulong b3 = (value >> 16) & 0xff;
ulong b4 = (value >> 24) & 0xff;
ulong b5 = (value >> 32) & 0xff;
ulong b6 = (value >> 40) & 0xff;
ulong b7 = (value >> 48) & 0xff;
ulong b8 = (value >> 56) & 0xff;
return b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8 << 0;
}
/// <summary>
/// Reverses a float.
/// </summary>
/// <param name="value">The float to reverse.</param>
/// <returns>The reversed float.</returns>
public static float Reverse(float value)
{
byte[] floatAsBytes = BitConverter.GetBytes(value);
Array.Reverse(floatAsBytes);
return BitConverter.ToSingle(floatAsBytes, 0);
}
/// <summary>
/// Reverses a double.
/// </summary>
/// <param name="value">The double to reverse.</param>
/// <returns>The reversed double.</returns>
public static double Reverse(double value)
{
byte[] doubleAsBytes = BitConverter.GetBytes(value);
Array.Reverse(doubleAsBytes);
return BitConverter.ToDouble(doubleAsBytes, 0);
}
}
}

Просмотреть файл

@ -0,0 +1,108 @@
//-----------------------------------------------------------------------
// <copyright file="IJsonNavigator.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System.Collections.Generic;
/// <summary>
/// JsonNavigator interface for classes that can navigate jsons.
/// </summary>
internal interface IJsonNavigator
{
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the IJsonNavigator.
/// </summary>
JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Gets <see cref="IJsonNavigatorNode"/> of the root node.
/// </summary>
/// <returns><see cref="IJsonNavigatorNode"/> corresponding to the root node.</returns>
IJsonNavigatorNode GetRootNode();
/// <summary>
/// Gets the <see cref="JsonNodeType"/> type for a particular node
/// </summary>
/// <param name="node">The <see cref="IJsonNavigatorNode"/> of the node you want to know the type of</param>
/// <returns><see cref="JsonNodeType"/> for the node</returns>
JsonNodeType GetNodeType(IJsonNavigatorNode node);
/// <summary>
/// Gets the numeric value for a node
/// </summary>
/// <param name="numberNode">The <see cref="IJsonNavigatorNode"/> of the node you want the number value from.</param>
/// <returns>A double that represents the number value in the node.</returns>
double GetNumberValue(IJsonNavigatorNode numberNode);
/// <summary>
/// Tries to get the buffered string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the buffered string from.</param>
/// <param name="bufferedStringValue">The buffered string value if possible</param>
/// <returns><code>true</code> if the JsonNavigator successfully got the buffered string value; <code>false</code> if the JsonNavigator failed to get the buffered string value.</returns>
bool TryGetBufferedStringValue(IJsonNavigatorNode stringNode, out IReadOnlyList<byte> bufferedStringValue);
/// <summary>
/// Gets a string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the string value from.</param>
/// <returns>The string value from the node.</returns>
string GetStringValue(IJsonNavigatorNode stringNode);
/// <summary>
/// Gets the number of elements in an array node.
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to get the count of.</param>
/// <returns>The number of elements in the array node.</returns>
int GetArrayItemCount(IJsonNavigatorNode arrayNode);
/// <summary>
/// Gets the node at a particular index of an array node
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to index from.</param>
/// <param name="index">The offset into the array</param>
/// <returns>The <see cref="IJsonNavigatorNode"/> of the node at a particular index of an array node</returns>
IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNode, int index);
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the array to get the items from</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.</returns>
IEnumerable<IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNode);
/// <summary>
/// Gets the number of properties in an object node.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of node to get the property count from.</param>
/// <returns>The number of properties in an object node.</returns>
int GetObjectPropertyCount(IJsonNavigatorNode objectNode);
/// <summary>
/// Tries to get a object property from an object with a particular property name.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of object node to get a property from.</param>
/// <param name="propertyName">The name of the property to search for.</param>
/// <param name="objectProperty">The <see cref="ObjectProperty"/> with the specified property name if it exists.</param>
/// <returns><code>true</code> if the JsonNavigator successfully found the <see cref="IJsonNavigatorNode"/> with the specified property name; <code>false</code> otherwise.</returns>
bool TryGetObjectProperty(IJsonNavigatorNode objectNode, string propertyName, out ObjectProperty objectProperty);
/// <summary>
/// Gets an IEnumerable of <see cref="ObjectProperty"/> properties from an object node.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of object node to get the properties from.</param>
/// <returns>The IEnumerable of <see cref="ObjectProperty"/> properties from an object node.</returns>
IEnumerable<ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNode);
/// <summary>
/// Tries to get the buffered raw json
/// </summary>
/// <param name="jsonNode">The json node of interest</param>
/// <param name="bufferedRawJson">The raw json.</param>
/// <returns>True if bufferedRawJson was set. False otherwise.</returns>
bool TryGetBufferedRawJson(IJsonNavigatorNode jsonNode, out IReadOnlyList<byte> bufferedRawJson);
}
}

Просмотреть файл

@ -0,0 +1,14 @@
//-----------------------------------------------------------------------
// <copyright file="IJsonNavigatorNode.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
/// <summary>
/// Interface that describes a Node within a JSON document in a <see cref="IJsonNavigator"/>
/// </summary>
internal interface IJsonNavigatorNode
{
}
}

Просмотреть файл

@ -0,0 +1,54 @@
//-----------------------------------------------------------------------
// <copyright file="IJsonReader.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System.Collections.Generic;
/// <summary>
/// Interface for all JsonReaders that know how to read jsons.
/// </summary>
internal interface IJsonReader
{
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the JsonReader
/// </summary>
JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Gets the current level of nesting of the JSON that the JsonReader is reading.
/// </summary>
int CurrentDepth { get; }
/// <summary>
/// Gets the <see cref="JsonTokenType"/> of the current token that the JsonReader is about to read.
/// </summary>
JsonTokenType CurrentTokenType { get; }
/// <summary>
/// Advances the JsonReader by one token.
/// </summary>
/// <returns><code>true</code> if the JsonReader successfully advanced to the next token; <code>false</code> if the JsonReader has passed the end of the JSON.</returns>
bool Read();
/// <summary>
/// Gets the next JSON token from the JsonReader as a double.
/// </summary>
/// <returns>The next JSON token from the JsonReader as a double.</returns>
double GetNumberValue();
/// <summary>
/// Gets the next JSON token from the JsonReader as a string.
/// </summary>
/// <returns>The next JSON token from the JsonReader as a string.</returns>
string GetStringValue();
/// <summary>
/// Gets current JSON token from the JsonReader as a raw series of bytes that is buffered.
/// </summary>
/// <returns>The current JSON token from the JsonReader as a raw series of bytes that is buffered.</returns>
IReadOnlyList<byte> GetBufferedRawJsonToken();
}
}

Просмотреть файл

@ -0,0 +1,111 @@
//-----------------------------------------------------------------------
// <copyright file="IJsonWriter.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System.Collections.Generic;
/// <summary>
/// Interface for all JsonWriters that know how to write jsons of a specific serialization format.
/// </summary>
internal interface IJsonWriter
{
/// <summary>
/// Gets the SerializationFormat of the JsonWriter.
/// </summary>
JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Gets the current length of the internal buffer.
/// </summary>
long CurrentLength { get; }
/// <summary>
/// Writes the object start symbol to internal buffer.
/// </summary>
void WriteObjectStart();
/// <summary>
/// Writes the object end symbol to the internal buffer.
/// </summary>
void WriteObjectEnd();
/// <summary>
/// Writes the array start symbol to the internal buffer.
/// </summary>
void WriteArrayStart();
/// <summary>
/// Writes the array end symbol to the internal buffer.
/// </summary>
void WriteArrayEnd();
/// <summary>
/// Writes a field name to the the internal buffer.
/// </summary>
/// <param name="fieldName">The name of the field to write.</param>
void WriteFieldName(string fieldName);
/// <summary>
/// Writes a string to the internal buffer.
/// </summary>
/// <param name="value">The value of the string to write.</param>
void WriteStringValue(string value);
/// <summary>
/// Writes an integer to the internal buffer.
/// </summary>
/// <param name="value">The value of the integer to write.</param>
void WriteIntValue(long value);
/// <summary>
/// Writes a number to the internal buffer.
/// </summary>
/// <param name="value">The value of the number to write.</param>
void WriteNumberValue(double value);
/// <summary>
/// Writes a boolean to the internal buffer.
/// </summary>
/// <param name="value">The value of the boolean to write.</param>
void WriteBoolValue(bool value);
/// <summary>
/// Writes a null to the internal buffer.
/// </summary>
void WriteNullValue();
/// <summary>
/// Writes current token from a json reader to the internal buffer.
/// </summary>
/// <param name="jsonReader">The JsonReader to the get the current token from.</param>
void WriteCurrentToken(IJsonReader jsonReader);
/// <summary>
/// Writes every token from the JsonReader to the internal buffer.
/// </summary>
/// <param name="jsonReader">The JsonReader to get the tokens from.</param>
void WriteAll(IJsonReader jsonReader);
/// <summary>
/// Writes a fragment of a json to the internal buffer
/// </summary>
/// <param name="jsonFragment">A section of a valid json</param>
void WriteJsonFragment(IReadOnlyList<byte> jsonFragment);
/// <summary>
/// Writes a json node to the internal buffer.
/// </summary>
/// <param name="jsonNavigator">The navigator to use to navigate the node</param>
/// <param name="jsonNavigatorNode">The node to write.</param>
void WriteJsonNode(IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode);
/// <summary>
/// Gets the result of the JsonWriter.
/// </summary>
/// <returns>The result of the JsonWriter as an array of bytes.</returns>
byte[] GetResult();
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,261 @@
//-----------------------------------------------------------------------
// <copyright file="NewtonsoftReader.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
/// <summary>
/// Wrapper class that implements a Newtonsoft JsonReader,
/// but forwards all the calls to a CosmosDB JSON reader.
/// </summary>
internal sealed class JsonCosmosDBReader : Newtonsoft.Json.JsonReader
{
/// <summary>
/// Singleton boxed value for null.
/// </summary>
private static readonly object Null = null;
/// <summary>
/// Singleton boxed value for false.
/// </summary>
private static readonly object False = false;
/// <summary>
/// Singleton boxed value for true.
/// </summary>
private static readonly object True = true;
/// <summary>
/// The CosmosDB JSON Reader that will be used for implementation.
/// </summary>
private readonly IJsonReader jsonReader;
/// <summary>
/// Initializes a new instance of the NewtonsoftReader class.
/// </summary>
/// <param name="stream">The stream to read from.</param>
public JsonCosmosDBReader(Stream stream)
{
this.jsonReader = JsonReader.Create(stream);
}
/// <summary>
/// Reads the next token from the reader.
/// </summary>
/// <returns>True if a token was read, else false.</returns>
public override bool Read()
{
bool read = this.jsonReader.Read();
if (!read)
{
this.SetToken(JsonToken.None);
return false;
}
JsonTokenType jsonTokenType = this.jsonReader.CurrentTokenType;
JsonToken newtonsoftToken;
object value;
switch (jsonTokenType)
{
case JsonTokenType.BeginArray:
newtonsoftToken = JsonToken.StartArray;
value = JsonCosmosDBReader.Null;
break;
case JsonTokenType.EndArray:
newtonsoftToken = JsonToken.EndArray;
value = JsonCosmosDBReader.Null;
break;
case JsonTokenType.BeginObject:
newtonsoftToken = JsonToken.StartObject;
value = JsonCosmosDBReader.Null;
break;
case JsonTokenType.EndObject:
newtonsoftToken = JsonToken.EndObject;
value = JsonCosmosDBReader.Null;
break;
case JsonTokenType.String:
newtonsoftToken = JsonToken.String;
value = this.jsonReader.GetStringValue();
break;
case JsonTokenType.Number:
value = this.jsonReader.GetNumberValue();
if ((double)value % 1 == 0)
{
newtonsoftToken = JsonToken.Integer;
}
else
{
newtonsoftToken = JsonToken.Float;
}
break;
case JsonTokenType.True:
newtonsoftToken = JsonToken.Boolean;
value = JsonCosmosDBReader.True;
break;
case JsonTokenType.False:
newtonsoftToken = JsonToken.Boolean;
value = JsonCosmosDBReader.False;
break;
case JsonTokenType.Null:
newtonsoftToken = JsonToken.Null;
value = JsonCosmosDBReader.Null;
break;
case JsonTokenType.FieldName:
newtonsoftToken = JsonToken.PropertyName;
value = this.jsonReader.GetStringValue();
break;
default:
throw new ArgumentException($"Unexpected jsonTokenType: {jsonTokenType}");
}
this.SetToken(newtonsoftToken, value);
return read;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="Byte"/>[].
/// </summary>
/// <returns>A <see cref="Byte"/>[] or <c>null</c> if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
public override byte[] ReadAsBytes()
{
this.Read();
byte[] value = this.jsonReader.GetBufferedRawJsonToken().ToArray();
this.SetToken(JsonToken.Bytes, value);
return value;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="DateTime"/>.
/// </summary>
/// <returns>A <see cref="Nullable{T}"/> of <see cref="DateTime"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTime? ReadAsDateTime()
{
DateTime? dateTime = (DateTime?)this.ReadAsTypeFromString<DateTime>(DateTime.Parse);
if (dateTime != null)
{
this.SetToken(JsonToken.Date, dateTime);
}
return dateTime;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/>.
/// </summary>
/// <returns>A <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTimeOffset? ReadAsDateTimeOffset()
{
DateTimeOffset? dateTimeOffset = (DateTimeOffset?)this.ReadAsTypeFromString<DateTimeOffset>(DateTimeOffset.Parse);
if (dateTimeOffset != null)
{
this.SetToken(JsonToken.Date, dateTimeOffset);
}
return dateTimeOffset;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="Decimal"/>.
/// </summary>
/// <returns>A <see cref="Nullable{T}"/> of <see cref="Decimal"/>. This method will return <c>null</c> at the end of an array.</returns>
public override decimal? ReadAsDecimal()
{
decimal? value = (decimal?)this.ReadNumberValue();
if (value != null)
{
this.SetToken(JsonToken.Float, value);
}
return value;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="Int32"/>.
/// </summary>
/// <returns>A <see cref="Nullable{T}"/> of <see cref="Int32"/>. This method will return <c>null</c> at the end of an array.</returns>
public override int? ReadAsInt32()
{
int? value = (int?)this.ReadNumberValue();
if (value != null)
{
this.SetToken(JsonToken.Integer, value);
}
return value;
}
/// <summary>
/// Reads the next JSON token from the source as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string ReadAsString()
{
string value = (string)this.ReadAsTypeFromString<string>((x) => x);
if (value != null)
{
this.SetToken(JsonToken.String, value);
}
return value;
}
/// <summary>
/// Reads the next string token and deserializes it to a type.
/// </summary>
/// <typeparam name="T">The type to deserialize to.</typeparam>
/// <param name="parse">The function that deserializes the token.</param>
/// <returns>The next string token deserialized to a type or null if at the end of an array.</returns>
private object ReadAsTypeFromString<T>(Func<string, T> parse)
{
this.Read();
object value;
if (this.jsonReader.CurrentTokenType == JsonTokenType.EndArray)
{
value = null;
}
else
{
string stringValue = this.jsonReader.GetStringValue();
value = parse(stringValue);
}
return value;
}
/// <summary>
/// Reads the next number token but returns null at the end of an array.
/// </summary>
/// <returns>The next number token but returns null at the end of an array.</returns>
private double? ReadNumberValue()
{
this.Read();
double? value;
if (this.jsonReader.CurrentTokenType == JsonTokenType.EndArray)
{
value = null;
}
else
{
value = this.jsonReader.GetNumberValue();
}
return value;
}
}
}

Просмотреть файл

@ -0,0 +1,377 @@
//-----------------------------------------------------------------------
// <copyright file="NewtonsoftWriter.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.IO;
using System.Text;
/// <summary>
/// Wrapper class that implements Newtonsoft's JsonWriter,
/// but calls into a CosmosDB JsonWriter for the implementation.
/// </summary>
internal sealed class JsonCosmosDBWriter : Newtonsoft.Json.JsonWriter
{
/// <summary>
/// A CosmosDB JSON writer used for the actual implementation.
/// </summary>
private readonly IJsonWriter jsonWriter;
/// <summary>
/// Initializes a new instance of the NewtonsoftWriter class.
/// </summary>
/// <param name="jsonSerializationFormat">The SerializationFormat to use.</param>
public JsonCosmosDBWriter(JsonSerializationFormat jsonSerializationFormat)
{
this.jsonWriter = JsonWriter.Create(jsonSerializationFormat);
}
/// <summary>
/// Flushes whatever is in the buffer to the underlying <see cref="Stream"/> and also flushes the underlying stream.
/// </summary>
public override void Flush()
{
this.jsonWriter.GetResult();
}
/// <summary>
/// Writes a comment <c>/*...*/</c> containing the specified text.
/// </summary>
/// <param name="text">Text to place inside the comment.</param>
public override void WriteComment(string text)
{
throw new NotSupportedException("Cannot write JSON comment.");
}
/// <summary>
/// Writes the end of an array.
/// </summary>
public override void WriteEndArray()
{
base.WriteEndArray();
this.jsonWriter.WriteArrayEnd();
}
/// <summary>
/// Writes the end constructor.
/// </summary>
public override void WriteEndConstructor()
{
throw new NotSupportedException("Cannot write end constructor.");
}
/// <summary>
/// Writes the end of a JSON object.
/// </summary>
public override void WriteEndObject()
{
base.WriteEndObject();
this.jsonWriter.WriteObjectEnd();
}
/// <summary>
/// Writes a null value.
/// </summary>
public override void WriteNull()
{
base.WriteNull();
this.jsonWriter.WriteNullValue();
}
/// <summary>
/// Writes the property name of a name/value pair on a JSON object.
/// </summary>
/// <param name="name">The name of the property.</param>
public override void WritePropertyName(string name)
{
this.WritePropertyName(name, false);
}
/// <summary>
/// Writes the property name of a name/value pair on a JSON object.
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="escape">Whether or not to escape the name</param>
public override void WritePropertyName(string name, bool escape)
{
base.WritePropertyName(name);
this.jsonWriter.WriteFieldName(name);
}
/// <summary>
/// Writes the start of a constructor with the given name.
/// </summary>
/// <param name="name">The name of the constructor.</param>
public override void WriteStartConstructor(string name)
{
throw new NotSupportedException("Cannot write Start constructor.");
}
/// <summary>
/// Writes raw JSON.
/// </summary>
/// <param name="json">The raw JSON to write.</param>
public override void WriteRaw(string json)
{
IJsonReader jsonReader = JsonReader.Create(Encoding.UTF8.GetBytes(json));
this.jsonWriter.WriteAll(jsonReader);
}
/// <summary>
/// Writes raw JSON where a value is expected and updates the writer's state.
/// </summary>
/// <param name="json">The raw JSON to write.</param>
public override void WriteRawValue(string json)
{
IJsonReader jsonReader = JsonReader.Create(Encoding.UTF8.GetBytes(json));
this.jsonWriter.WriteAll(jsonReader);
}
/// <summary>
/// Writes the beginning of a JSON array.
/// </summary>
public override void WriteStartArray()
{
base.WriteStartArray();
this.jsonWriter.WriteArrayStart();
}
/// <summary>
/// Writes the beginning of a JSON object.
/// </summary>
public override void WriteStartObject()
{
base.WriteStartObject();
this.jsonWriter.WriteObjectStart();
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public override void WriteUndefined()
{
throw new NotSupportedException("Can not write undefined");
}
#region WriteValue methods
/// <summary>
/// Writes a <see cref="Object"/> value.
/// An error will raised if the value cannot be written as a single JSON token.
/// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param>
public override void WriteValue(object value)
{
if (value is string)
{
this.WriteValue((string)value);
}
else
{
this.WriteValue((double)value);
}
}
/// <summary>
/// Writes a <see cref="String"/> value.
/// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string value)
{
base.WriteValue(value);
this.jsonWriter.WriteStringValue(value);
}
/// <summary>
/// Writes a <see cref="Int32"/> value.
/// </summary>
/// <param name="value">The <see cref="Int32"/> value to write.</param>
public override void WriteValue(int value)
{
this.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="UInt32"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
public override void WriteValue(uint value)
{
this.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="Int64"/> value.
/// </summary>
/// <param name="value">The <see cref="Int64"/> value to write.</param>
public override void WriteValue(long value)
{
base.WriteValue(value);
this.jsonWriter.WriteIntValue(value);
}
/// <summary>
/// Writes a <see cref="UInt64"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
public override void WriteValue(ulong value)
{
if(value <= long.MaxValue)
{
this.WriteValue((long)value);
}
else
{
this.WriteValue((double)value);
}
}
/// <summary>
/// Writes a <see cref="Single"/> value.
/// </summary>
/// <param name="value">The <see cref="Single"/> value to write.</param>
public override void WriteValue(float value)
{
this.WriteValue((double)value);
}
/// <summary>
/// Writes a <see cref="Double"/> value.
/// </summary>
/// <param name="value">The <see cref="Double"/> value to write.</param>
public override void WriteValue(double value)
{
base.WriteValue(value);
this.jsonWriter.WriteNumberValue(value);
}
/// <summary>
/// Writes a <see cref="Boolean"/> value.
/// </summary>
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
public override void WriteValue(bool value)
{
base.WriteValue(value);
this.jsonWriter.WriteBoolValue(value);
}
/// <summary>
/// Writes a <see cref="Int16"/> value.
/// </summary>
/// <param name="value">The <see cref="Int16"/> value to write.</param>
public override void WriteValue(short value)
{
base.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="UInt16"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
public override void WriteValue(ushort value)
{
this.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="Char"/> value.
/// </summary>
/// <param name="value">The <see cref="Char"/> value to write.</param>
public override void WriteValue(char value)
{
base.WriteValue(value);
this.jsonWriter.WriteStringValue(value.ToString());
}
/// <summary>
/// Writes a <see cref="Byte"/> value.
/// </summary>
/// <param name="value">The <see cref="Byte"/> value to write.</param>
public override void WriteValue(byte value)
{
this.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="SByte"/> value.
/// </summary>
/// <param name="value">The <see cref="SByte"/> value to write.</param>
public override void WriteValue(sbyte value)
{
this.WriteValue((long)value);
}
/// <summary>
/// Writes a <see cref="Decimal"/> value.
/// </summary>
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
public override void WriteValue(decimal value)
{
this.WriteValue((double)value);
}
/// <summary>
/// Writes a <see cref="DateTime"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public override void WriteValue(DateTime value)
{
this.WriteValue(value.ToString());
}
/// <summary>
/// Writes a <see cref="Byte"/>[] value.
/// </summary>
/// <param name="value">The <see cref="Byte"/>[] value to write.</param>
public override void WriteValue(byte[] value)
{
throw new NotSupportedException("Can not write byte arrays");
}
/// <summary>
/// Writes a <see cref="Guid"/> value.
/// </summary>
/// <param name="value">The <see cref="Guid"/> value to write.</param>
public override void WriteValue(Guid value)
{
this.WriteValue(value.ToString());
}
/// <summary>
/// Writes a <see cref="TimeSpan"/> value.
/// </summary>
/// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
public override void WriteValue(TimeSpan value)
{
this.WriteValue(value.ToString());
}
/// <summary>
/// Writes a <see cref="Uri"/> value.
/// </summary>
/// <param name="value">The <see cref="Uri"/> value to write.</param>
public override void WriteValue(Uri value)
{
if (value == null)
{
this.WriteNull();
}
else
{
this.WriteValue(value.ToString());
}
}
#endregion
/// <summary>
/// Gets the result of all the tokens written so far.
/// </summary>
/// <returns>The result of all the tokens written so far.</returns>
public byte[] GetResult()
{
return this.jsonWriter.GetResult();
}
}
}

Просмотреть файл

@ -0,0 +1,473 @@
//-----------------------------------------------------------------------
// <copyright file="JsonNavigator.JsonBinaryNavigator.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
using System.IO;
/// <summary>
/// Partial class that wraps the private JsonTextNavigator
/// </summary>
internal abstract partial class JsonNavigator : IJsonNavigator
{
/// <summary>
/// JsonNavigator that know how to navigate JSONs in binary serialization.
/// </summary>
private sealed class JsonBinaryNavigator : JsonNavigator
{
private readonly BinaryNode rootNode;
private readonly LittleEndianBinaryReader binaryReader;
private readonly byte[] buffer;
/// <summary>
/// Initializes a new instance of the JsonBinaryNavigator class
/// </summary>
/// <param name="buffer">The (UTF-8) buffer to navigate.</param>
/// <param name="skipValidation">whether to skip validation or not.</param>
public JsonBinaryNavigator(byte[] buffer, bool skipValidation = false)
{
if (buffer == null)
{
throw new ArgumentNullException($"{nameof(buffer)} can not be null");
}
if(buffer.Length < 1)
{
throw new ArgumentException($"{nameof(buffer)} must have at least one byte.");
}
this.rootNode = new BinaryNode(1, JsonBinaryEncoding.GetNodeType(buffer[1]));
// false, since stream is not writeable
// true, since buffer is visible
this.binaryReader = new LittleEndianBinaryReader(new MemoryStream(buffer, 0, buffer.Length, false, true));
this.buffer = buffer;
}
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the IJsonNavigator.
/// </summary>
public override JsonSerializationFormat SerializationFormat
{
get
{
return JsonSerializationFormat.Binary;
}
}
/// <summary>
/// Gets <see cref="IJsonNavigatorNode"/> of the root node.
/// </summary>
/// <returns><see cref="IJsonNavigatorNode"/> corresponding to the root node.</returns>
public override IJsonNavigatorNode GetRootNode()
{
return this.rootNode;
}
/// <summary>
/// Gets the <see cref="JsonNodeType"/> type for a particular node
/// </summary>
/// <param name="node">The <see cref="IJsonNavigatorNode"/> of the node you want to know the type of</param>
/// <returns><see cref="JsonNodeType"/> for the node</returns>
public override JsonNodeType GetNodeType(IJsonNavigatorNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
if ((node as BinaryNode) == null)
{
throw new ArgumentException($"{nameof(node)} must be a binary node.");
}
return ((BinaryNode)node).JsonNodeType;
}
/// <summary>
/// Gets the numeric value for a node
/// </summary>
/// <param name="numberNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the node you want the number value from.</param>
/// <returns>A double that represents the number value in the node.</returns>
public override double GetNumberValue(IJsonNavigatorNode numberNavigatorNode)
{
if (numberNavigatorNode == null)
{
throw new ArgumentNullException(nameof(numberNavigatorNode));
}
if (!(((numberNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Number))
{
throw new ArgumentException($"{nameof(numberNavigatorNode)} must be a binary number node.");
}
long offset = ((BinaryNode)numberNavigatorNode).Offset;
this.binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
return JsonBinaryEncoding.GetNumberValue(this.binaryReader);
}
/// <summary>
/// Tries to get the buffered string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the buffered string from.</param>
/// <param name="bufferedStringValue">The buffered string value if possible</param>
/// <returns><code>true</code> if the JsonNavigator successfully got the buffered string value; <code>false</code> if the JsonNavigator failed to get the buffered string value.</returns>
public override bool TryGetBufferedStringValue(IJsonNavigatorNode stringNode, out IReadOnlyList<byte> bufferedStringValue)
{
//TODO (brchon): implement this when optimizing code.
bufferedStringValue = null;
return false;
}
/// <summary>
/// Gets a string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the string value from.</param>
/// <returns>The string value from the node.</returns>
public override string GetStringValue(IJsonNavigatorNode stringNode)
{
if (stringNode == null)
{
throw new ArgumentNullException(nameof(stringNode));
}
if (!((((stringNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.String) ||
(((stringNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.FieldName)))
{
throw new ArgumentException($"{nameof(stringNode)} must be a binary string or fieldname node.");
}
long offset = ((BinaryNode)stringNode).Offset;
this.binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
return JsonBinaryEncoding.GetStringValue(this.binaryReader);
}
/// <summary>
/// Gets the number of elements in an array node.
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to get the count of.</param>
/// <returns>The number of elements in the array node.</returns>
public override int GetArrayItemCount(IJsonNavigatorNode arrayNavigatorNode)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException(nameof(arrayNavigatorNode));
}
if (!(((arrayNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Array))
{
throw new ArgumentException($"{nameof(arrayNavigatorNode)} must be a binary array node.");
}
int offset = ((BinaryNode)arrayNavigatorNode).Offset;
byte typeMarker = this.buffer[offset];
int firstValueOffset = offset + JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
long count;
switch (typeMarker)
{
// Empty and Single Array
case JsonBinaryEncoding.TypeMarker.EmptyArray:
count = 0;
break;
case JsonBinaryEncoding.TypeMarker.SingleItemArray:
count = 1;
break;
// Arrays with length and count prefix
case JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount:
count = this.buffer[offset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength];
break;
case JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount:
count = BitConverter.ToUInt16(this.buffer, offset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength);
break;
case JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount:
count = BitConverter.ToUInt32(this.buffer, offset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength);
break;
// Arrays with length prefix
case JsonBinaryEncoding.TypeMarker.Array1ByteLength:
count = this.GetValueCount(firstValueOffset, this.buffer[offset + JsonBinaryEncoding.TypeMarkerLength]);
break;
case JsonBinaryEncoding.TypeMarker.Array2ByteLength:
count = this.GetValueCount(firstValueOffset, BitConverter.ToUInt16(this.buffer, offset + JsonBinaryEncoding.TypeMarkerLength));
break;
case JsonBinaryEncoding.TypeMarker.Array4ByteLength:
count = this.GetValueCount(firstValueOffset, BitConverter.ToUInt32(this.buffer, offset + JsonBinaryEncoding.TypeMarkerLength));
break;
default:
throw new InvalidOperationException($"Unexpected array type marker: {typeMarker}");
}
if (count > int.MaxValue)
{
throw new InvalidOperationException("count can not be more than int.MaxValue");
}
return (int)count;
}
/// <summary>
/// Gets the node at a particular index of an array node
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to index from.</param>
/// <param name="index">The offset into the array</param>
/// <returns>The <see cref="IJsonNavigatorNode"/> of the node at a particular index of an array node</returns>
public override IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNavigatorNode, int index)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException(nameof(arrayNavigatorNode));
}
if (!(((arrayNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Array))
{
throw new ArgumentException($"{nameof(arrayNavigatorNode)} must be a binary array node.");
}
// TODO (brchon): We can optimize for the case where the count is serialized so we can avoid using the linear time call to TryGetValueAt().
int arrayOffset = ((BinaryNode)arrayNavigatorNode).Offset;
byte typeMarker = this.buffer[arrayOffset];
BinaryNode node;
long firstArrayItemOffset = arrayOffset + JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
long arrayLength = JsonBinaryEncoding.GetValueLength(this.buffer, arrayOffset);
long arrayItemsLength = arrayLength - (firstArrayItemOffset - arrayOffset);
if (!this.TryGetValueAt(firstArrayItemOffset, arrayItemsLength, index, out node))
{
throw new IndexOutOfRangeException($"Tried to access index:{index} in an array.");
}
return node;
}
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the array to get the items from</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.</returns>
public override IEnumerable<IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNavigatorNode)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException(nameof(arrayNavigatorNode));
}
if (!(((arrayNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Array))
{
throw new ArgumentException($"{nameof(arrayNavigatorNode)} must be a binary array node.");
}
int arrayOffset = ((BinaryNode)arrayNavigatorNode).Offset;
byte typeMarker = this.buffer[arrayOffset];
long arrayLength = JsonBinaryEncoding.GetValueLength(this.buffer, arrayOffset);
long firstValueOffset = arrayOffset + JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
long bytesToProcess = (arrayOffset + arrayLength) - firstValueOffset;
for (int bytesProcessed = 0; bytesProcessed < bytesToProcess; bytesProcessed += (int)JsonBinaryEncoding.GetValueLength(this.buffer, firstValueOffset + bytesProcessed))
{
yield return this.CreateBinaryNode((int)(firstValueOffset + bytesProcessed));
}
}
/// <summary>
/// Gets the number of properties in an object node.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="IJsonNavigatorNode"/> of node to get the property count from.</param>
/// <returns>The number of properties in an object node.</returns>
public override int GetObjectPropertyCount(IJsonNavigatorNode objectNavigatorNode)
{
if (objectNavigatorNode == null)
{
throw new ArgumentNullException(nameof(objectNavigatorNode));
}
if (!(((objectNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Object))
{
throw new ArgumentException($"{nameof(objectNavigatorNode)} must be a binary object node.");
}
int objectOffset = ((BinaryNode)objectNavigatorNode).Offset;
byte typeMarker = this.buffer[objectOffset];
int firstObjectPropertyOffset = objectOffset + JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
long count;
switch (typeMarker)
{
// Empty and Single Object
case JsonBinaryEncoding.TypeMarker.EmptyObject:
count = 0;
break;
case JsonBinaryEncoding.TypeMarker.SinglePropertyObject:
// This number gets divided by 2 later.
count = 2;
break;
// Object with length and count prefix
case JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount:
count = this.buffer[objectOffset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength];
break;
case JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount:
count = BitConverter.ToUInt16(this.buffer, objectOffset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength);
break;
case JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount:
count = BitConverter.ToUInt32(this.buffer, objectOffset + JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength);
break;
// Object with length prefix
case JsonBinaryEncoding.TypeMarker.Object1ByteLength:
count = this.GetValueCount(firstObjectPropertyOffset, this.buffer[objectOffset + JsonBinaryEncoding.TypeMarkerLength]);
break;
case JsonBinaryEncoding.TypeMarker.Object2ByteLength:
count = this.GetValueCount(firstObjectPropertyOffset, BitConverter.ToUInt16(this.buffer, objectOffset + JsonBinaryEncoding.TypeMarkerLength));
break;
case JsonBinaryEncoding.TypeMarker.Object4ByteLength:
count = this.GetValueCount(firstObjectPropertyOffset, BitConverter.ToUInt32(this.buffer, objectOffset + JsonBinaryEncoding.TypeMarkerLength));
break;
default:
throw new InvalidOperationException($"Unexpected object type marker: {typeMarker}");
}
// Divide by 2 since the count includes fieldname and value as seperate entities
count = count / 2;
if (count > int.MaxValue)
{
throw new InvalidOperationException("count can not be more than int.MaxValue");
}
return (int)count;
}
/// <summary>
/// Tries to get a object property from an object with a particular property name.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="ObjectProperty"/> of object node to get a property from.</param>
/// <param name="propertyName">The name of the property to search for.</param>
/// <param name="objectProperty">The <see cref="IJsonNavigatorNode"/> with the specified property name if it exists.</param>
/// <returns><code>true</code> if the JsonNavigator successfully found the <see cref="ObjectProperty"/> with the specified property name; <code>false</code> otherwise.</returns>
public override bool TryGetObjectProperty(IJsonNavigatorNode objectNavigatorNode, string propertyName, out ObjectProperty objectProperty)
{
foreach (ObjectProperty objectPropertyNode in this.GetObjectProperties(objectNavigatorNode))
{
if (this.GetStringValue(objectPropertyNode.NameNode) == propertyName)
{
objectProperty = objectPropertyNode;
return true;
}
}
objectProperty = default(ObjectProperty);
return false;
}
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/> properties from an object node.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="IJsonNavigatorNode"/> of object node to get the properties from.</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/> properties from an object node.</returns>
public override IEnumerable<ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNavigatorNode)
{
if (objectNavigatorNode == null)
{
throw new ArgumentNullException(nameof(objectNavigatorNode));
}
if (!(((objectNavigatorNode as BinaryNode)?.JsonNodeType ?? JsonNodeType.Unknown) == JsonNodeType.Object))
{
throw new ArgumentException($"{nameof(objectNavigatorNode)} must actually be a binary object node.");
}
int offset = ((BinaryNode)objectNavigatorNode).Offset;
byte typeMarker = this.buffer[offset];
long objectLength = JsonBinaryEncoding.GetValueLength(this.buffer, offset);
long firstValueOffset = offset + JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
long bytesToProcess = (offset + objectLength) - firstValueOffset;
for (int bytesProcessed = 0; bytesProcessed < bytesToProcess;)
{
BinaryNode nameNode = new BinaryNode((int)(firstValueOffset + bytesProcessed), JsonNodeType.FieldName);
bytesProcessed += (int)JsonBinaryEncoding.GetValueLength(this.buffer, firstValueOffset + bytesProcessed);
BinaryNode valueNode = this.CreateBinaryNode((int)(firstValueOffset + bytesProcessed));
bytesProcessed += (int)JsonBinaryEncoding.GetValueLength(this.buffer, firstValueOffset + bytesProcessed);
yield return new ObjectProperty(nameNode, valueNode);
}
}
/// <summary>
/// Tries to get the buffered raw json
/// </summary>
/// <param name="jsonNode">The json node of interest</param>
/// <param name="bufferedRawJson">The raw json.</param>
/// <returns>True if bufferedRawJson was set. False otherwise.</returns>
public override bool TryGetBufferedRawJson(IJsonNavigatorNode jsonNode, out IReadOnlyList<byte> bufferedRawJson)
{
throw new NotImplementedException();
}
private int GetValueCount(long offset, long length)
{
long bytesProcessed = 0;
int count = 0;
while (bytesProcessed < length)
{
count++;
bytesProcessed += JsonBinaryEncoding.GetValueLength(this.buffer, offset + bytesProcessed);
}
return count;
}
private bool TryGetValueAt(long offset, long length, long index, out BinaryNode node)
{
long currentOffset = offset;
for (long count = 0; count < index; count++)
{
long valueLength = JsonBinaryEncoding.GetValueLength(this.buffer, currentOffset);
if (valueLength == 0)
{
node = default(BinaryNode);
return false;
}
currentOffset += valueLength;
if (currentOffset >= (offset + length))
{
node = default(BinaryNode);
return false;
}
}
if (currentOffset > int.MaxValue)
{
throw new InvalidOperationException($"{nameof(currentOffset)} is greater than int.MaxValue");
}
node = this.CreateBinaryNode((int)currentOffset);
return true;
}
private BinaryNode CreateBinaryNode(int offset)
{
return new BinaryNode(offset, JsonBinaryEncoding.GetNodeType(this.buffer[offset]));
}
private class BinaryNode : IJsonNavigatorNode
{
public BinaryNode(int offset, JsonNodeType jsonNodeType)
{
this.Offset = offset;
this.JsonNodeType = jsonNodeType;
}
public int Offset { get; }
public JsonNodeType JsonNodeType { get; }
}
}
}
}

Просмотреть файл

@ -0,0 +1,752 @@
//-----------------------------------------------------------------------
// <copyright file="JsonNavigator.JsonTextNavigator.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
/// <summary>
/// Partial class that wraps the private JsonTextNavigator
/// </summary>
internal abstract partial class JsonNavigator : IJsonNavigator
{
/// <summary>
/// JsonNavigator that know how to navigate JSONs in text serialization.
/// Internally the navigator uses a <see cref="JsonTextParser"/> to from an AST of the JSON and the rest of the methods are just letting you traverse the materialized tree.
/// </summary>
private sealed class JsonTextNavigator : JsonNavigator
{
private readonly JsonTextNode rootNode;
/// <summary>
/// Initializes a new instance of the JsonTextNavigator class
/// </summary>
/// <param name="buffer">The (UTF-8) buffer to navigate.</param>
/// <param name="skipValidation">whether to skip validation or not.</param>
public JsonTextNavigator(byte[] buffer, bool skipValidation = false)
{
IJsonReader jsonTextReader = JsonReader.Create(buffer, skipValidation);
if (jsonTextReader.SerializationFormat != JsonSerializationFormat.Text)
{
throw new ArgumentException("jsonTextReader's serialization format must actually be text");
}
this.rootNode = JsonTextParser.Parse(jsonTextReader);
}
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the IJsonNavigator.
/// </summary>
public override JsonSerializationFormat SerializationFormat
{
get
{
return JsonSerializationFormat.Text;
}
}
/// <summary>
/// Gets <see cref="IJsonNavigatorNode"/> of the root node.
/// </summary>
/// <returns><see cref="IJsonNavigatorNode"/> corresponding to the root node.</returns>
public override IJsonNavigatorNode GetRootNode()
{
return this.rootNode;
}
/// <summary>
/// Gets the <see cref="JsonNodeType"/> type for a particular node
/// </summary>
/// <param name="node">The <see cref="IJsonNavigatorNode"/> of the node you want to know the type of</param>
/// <returns><see cref="JsonNodeType"/> for the node</returns>
public override JsonNodeType GetNodeType(IJsonNavigatorNode node)
{
if (node == null)
{
throw new ArgumentNullException("node");
}
JsonTextNode jsonTextNode = node as JsonTextNode;
if (jsonTextNode == null)
{
throw new ArgumentException("node must actually be a text node.");
}
return jsonTextNode.JsonNodeType;
}
/// <summary>
/// Gets the numeric value for a node
/// </summary>
/// <param name="numberNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the node you want the number value from.</param>
/// <returns>A double that represents the number value in the node.</returns>
public override double GetNumberValue(IJsonNavigatorNode numberNavigatorNode)
{
if (numberNavigatorNode == null)
{
throw new ArgumentNullException("numberNavigatorNode");
}
NumberNode numberNode = numberNavigatorNode as NumberNode;
if (numberNode == null)
{
throw new ArgumentException("numberNavigatorNode must actually be a number node.");
}
return numberNode.Value;
}
/// <summary>
/// Tries to get the buffered string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the buffered string from.</param>
/// <param name="bufferedStringValue">The buffered string value if possible</param>
/// <returns><code>true</code> if the JsonNavigator successfully got the buffered string value; <code>false</code> if the JsonNavigator failed to get the buffered string value.</returns>
public override bool TryGetBufferedStringValue(IJsonNavigatorNode stringNode, out IReadOnlyList<byte> bufferedStringValue)
{
bufferedStringValue = null;
return false;
}
/// <summary>
/// Gets a string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the string value from.</param>
/// <returns>The string value from the node.</returns>
public override string GetStringValue(IJsonNavigatorNode stringNode)
{
if (stringNode == null)
{
throw new ArgumentNullException("stringNode");
}
StringNodeBase stringValueNode = stringNode as StringNodeBase;
if (stringValueNode == null)
{
throw new ArgumentException("stringNode must actually be a number node.");
}
return stringValueNode.Value;
}
/// <summary>
/// Gets the number of elements in an array node.
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to get the count of.</param>
/// <returns>The number of elements in the array node.</returns>
public override int GetArrayItemCount(IJsonNavigatorNode arrayNavigatorNode)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException("arrayNavigatorNode");
}
ArrayNode arrayNode = arrayNavigatorNode as ArrayNode;
if (arrayNode == null)
{
throw new ArgumentException("arrayNavigatorNode must actually be an array node");
}
return arrayNode.Items.Count;
}
/// <summary>
/// Gets the node at a particular index of an array node
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to index from.</param>
/// <param name="index">The offset into the array</param>
/// <returns>The <see cref="IJsonNavigatorNode"/> of the node at a particular index of an array node</returns>
public override IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNavigatorNode, int index)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException("arrayNode");
}
ArrayNode arrayNode = arrayNavigatorNode as ArrayNode;
if (arrayNode == null)
{
throw new ArgumentException("arrayNavigatorNode must actually be an array node");
}
return arrayNode.Items[index];
}
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.
/// </summary>
/// <param name="arrayNavigatorNode">The <see cref="IJsonNavigatorNode"/> of the array to get the items from</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.</returns>
public override IEnumerable<IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNavigatorNode)
{
if (arrayNavigatorNode == null)
{
throw new ArgumentNullException("arrayNode");
}
ArrayNode arrayNode = arrayNavigatorNode as ArrayNode;
if (arrayNode == null)
{
throw new ArgumentException("arrayNavigatorNode must actually be an array node");
}
return arrayNode.Items;
}
/// <summary>
/// Gets the number of properties in an object node.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="IJsonNavigatorNode"/> of node to get the property count from.</param>
/// <returns>The number of properties in an object node.</returns>
public override int GetObjectPropertyCount(IJsonNavigatorNode objectNavigatorNode)
{
if (objectNavigatorNode == null)
{
throw new ArgumentNullException("objectNode");
}
ObjectNode objectNode = objectNavigatorNode as ObjectNode;
if (objectNode == null)
{
throw new ArgumentException("objectNavigatorNode must actually be an array node");
}
return objectNode.Properties.Count;
}
/// <summary>
/// Tries to get a object property from an object with a particular property name.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="ObjectProperty"/> of object node to get a property from.</param>
/// <param name="propertyName">The name of the property to search for.</param>
/// <param name="objectProperty">The <see cref="IJsonNavigatorNode"/> with the specified property name if it exists.</param>
/// <returns><code>true</code> if the JsonNavigator successfully found the <see cref="ObjectProperty"/> with the specified property name; <code>false</code> otherwise.</returns>
public override bool TryGetObjectProperty(IJsonNavigatorNode objectNavigatorNode, string propertyName, out ObjectProperty objectProperty)
{
if (objectNavigatorNode == null)
{
throw new ArgumentNullException("objectNavigatorNode");
}
if (propertyName == null)
{
throw new ArgumentNullException("propertyName");
}
ObjectNode objectNode = objectNavigatorNode as ObjectNode;
if (objectNode == null)
{
throw new ArgumentException("objectNavigatorNode must actually be an array node");
}
objectProperty = default(ObjectProperty);
IReadOnlyList<ObjectProperty> properties = ((ObjectNode)objectNode).Properties;
foreach (ObjectProperty property in properties)
{
if (this.GetStringValue(property.NameNode) == propertyName)
{
objectProperty = property;
return true;
}
}
return false;
}
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/> properties from an object node.
/// </summary>
/// <param name="objectNavigatorNode">The <see cref="IJsonNavigatorNode"/> of object node to get the properties from.</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/> properties from an object node.</returns>
public override IEnumerable<ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNavigatorNode)
{
if (objectNavigatorNode == null)
{
throw new ArgumentNullException("objectNode");
}
ObjectNode objectNode = objectNavigatorNode as ObjectNode;
if (objectNode == null)
{
throw new ArgumentException("objectNavigatorNode must actually be an array node");
}
return objectNode.Properties;
}
/// <summary>
/// Tries to get the buffered raw json
/// </summary>
/// <param name="jsonNode">The json node of interest</param>
/// <param name="bufferedRawJson">The raw json.</param>
/// <returns>True if bufferedRawJson was set. False otherwise.</returns>
public override bool TryGetBufferedRawJson(IJsonNavigatorNode jsonNode, out IReadOnlyList<byte> bufferedRawJson)
{
throw new NotImplementedException();
}
#region JsonTextParser
/// <summary>
/// The JsonTextParser class is used to get a JSON AST / DOM from plaintext using a JsonTextReader as a lexer / tokenizer.
/// Internally the parser is implemented as an LL(1) parser, since JSON is unambiguous and we can just parse it using recursive decent.
/// </summary>
private static class JsonTextParser
{
/// <summary>
/// Gets the root node of a JSON AST from a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>The root node of a JSON AST from a jsonTextReader.</returns>
public static JsonTextNode Parse(IJsonReader jsonTextReader)
{
if (jsonTextReader.SerializationFormat != JsonSerializationFormat.Text)
{
throw new ArgumentException("jsonTextReader's serialization format must actually be text");
}
// Read past the json object not started state.
jsonTextReader.Read();
JsonTextNode rootNode = JsonTextParser.ParseNode(jsonTextReader);
// Make sure that we are at the end of the file.
if (jsonTextReader.Read())
{
throw new ArgumentException("Did not fully parse json");
}
return rootNode;
}
/// <summary>
/// Parses out a JSON array AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON array AST node</returns>
private static ArrayNode ParseArrayNode(IJsonReader jsonTextReader)
{
List<JsonTextNode> items = new List<JsonTextNode>();
// consume the begin array token
jsonTextReader.Read();
while (jsonTextReader.CurrentTokenType != JsonTokenType.EndArray)
{
items.Add(JsonTextParser.ParseNode(jsonTextReader));
}
// consume the end array token
jsonTextReader.Read();
return ArrayNode.Create(items);
}
/// <summary>
/// Parses out a JSON object AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON object AST node</returns>
private static ObjectNode ParseObjectNode(IJsonReader jsonTextReader)
{
List<ObjectProperty> properties = new List<ObjectProperty>();
// consume the begin object token
jsonTextReader.Read();
while (jsonTextReader.CurrentTokenType != JsonTokenType.EndObject)
{
ObjectProperty property = JsonTextParser.ParsePropertyNode(jsonTextReader);
properties.Add(property);
}
// consume the end object token
jsonTextReader.Read();
return ObjectNode.Create(properties);
}
/// <summary>
/// Parses out a JSON string AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON string AST node</returns>
private static StringNode ParseStringNode(IJsonReader jsonTextReader)
{
StringNode stringNode = StringNode.Create((ArraySegment<byte>)jsonTextReader.GetBufferedRawJsonToken());
// consume the string from the reader
jsonTextReader.Read();
return stringNode;
}
/// <summary>
/// Parses out a JSON number AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON number AST node</returns>
private static NumberNode ParseNumberNode(IJsonReader jsonTextReader)
{
NumberNode numberNode = NumberNode.Create((ArraySegment<byte>)jsonTextReader.GetBufferedRawJsonToken());
// consume the number from the reader
jsonTextReader.Read();
return numberNode;
}
/// <summary>
/// Parses out a JSON true AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON true AST node</returns>
private static TrueNode ParseTrueNode(IJsonReader jsonTextReader)
{
// consume the true token from the reader
jsonTextReader.Read();
return TrueNode.Create();
}
/// <summary>
/// Parses out a JSON false AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON true AST node</returns>
private static FalseNode ParseFalseNode(IJsonReader jsonTextReader)
{
// consume the false token from the reader
jsonTextReader.Read();
return FalseNode.Create();
}
/// <summary>
/// Parses out a JSON null AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON null AST node</returns>
private static NullNode ParseNullNode(IJsonReader jsonTextReader)
{
// consume the null token from the reader
jsonTextReader.Read();
return NullNode.Create();
}
/// <summary>
/// Parses out a JSON property AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON property AST node</returns>
private static ObjectProperty ParsePropertyNode(IJsonReader jsonTextReader)
{
FieldNameNode fieldName = FieldNameNode.Create((ArraySegment<byte>)jsonTextReader.GetBufferedRawJsonToken());
// Consume the fieldname from the jsonreader
jsonTextReader.Read();
JsonTextNode value = JsonTextParser.ParseNode(jsonTextReader);
return new ObjectProperty(fieldName, value);
}
/// <summary>
/// Parses out a JSON AST node with a jsonTextReader.
/// </summary>
/// <param name="jsonTextReader">The reader to use as a lexer / tokenizer</param>
/// <returns>JSON AST node (type determined by the reader)</returns>
private static JsonTextNode ParseNode(IJsonReader jsonTextReader)
{
JsonTextNode node;
switch (jsonTextReader.CurrentTokenType)
{
case JsonTokenType.BeginArray:
node = JsonTextParser.ParseArrayNode(jsonTextReader);
break;
case JsonTokenType.BeginObject:
node = JsonTextParser.ParseObjectNode(jsonTextReader);
break;
case JsonTokenType.String:
node = JsonTextParser.ParseStringNode(jsonTextReader);
break;
case JsonTokenType.Number:
node = JsonTextParser.ParseNumberNode(jsonTextReader);
break;
case JsonTokenType.True:
node = JsonTextParser.ParseTrueNode(jsonTextReader);
break;
case JsonTokenType.False:
node = JsonTextParser.ParseFalseNode(jsonTextReader);
break;
case JsonTokenType.Null:
node = JsonTextParser.ParseNullNode(jsonTextReader);
break;
default:
throw new JsonInvalidTokenException();
}
return node;
}
}
#endregion
#region Nodes
private sealed class ArrayNode : JsonTextNode
{
private static readonly ArrayNode Empty = new ArrayNode(new List<JsonTextNode>());
private readonly List<JsonTextNode> items;
private ArrayNode(List<JsonTextNode> items)
: base(JsonNodeType.Array)
{
this.items = items;
}
public IReadOnlyList<JsonTextNode> Items
{
get
{
return this.items;
}
}
public static ArrayNode Create(List<JsonTextNode> items)
{
if (items.Count == 0)
{
return ArrayNode.Empty;
}
return new ArrayNode(items);
}
}
private sealed class FalseNode : JsonTextNode
{
private static readonly FalseNode Instance = new FalseNode();
private FalseNode()
: base(JsonNodeType.False)
{
}
public static FalseNode Create()
{
return FalseNode.Instance;
}
}
private sealed class FieldNameNode : StringNodeBase
{
private static readonly FieldNameNode Empty = new FieldNameNode(string.Empty);
private FieldNameNode(ArraySegment<byte> bufferedToken)
: base(bufferedToken, false)
{
}
private FieldNameNode(string value)
: base(value, true)
{
}
public static FieldNameNode Create(ArraySegment<byte> bufferedToken)
{
if (bufferedToken.Count == 0)
{
return FieldNameNode.Empty;
}
// In the future we can have a flyweight dictionary for system strings.
return new FieldNameNode(bufferedToken);
}
}
private abstract class JsonTextNode : IJsonNavigatorNode
{
private readonly JsonNodeType jsonNodeType;
protected JsonTextNode(JsonNodeType jsonNodeType)
{
this.jsonNodeType = jsonNodeType;
}
public JsonNodeType JsonNodeType
{
get
{
return this.jsonNodeType;
}
}
}
private sealed class NullNode : JsonTextNode
{
private static readonly NullNode Instance = new NullNode();
private NullNode()
: base(JsonNodeType.Null)
{
}
public static NullNode Create()
{
return NullNode.Instance;
}
}
private sealed class NumberNode : JsonTextNode
{
private static readonly NumberNode[] LiteralNumberNodes = new NumberNode[]
{
new NumberNode(0), new NumberNode(1), new NumberNode(2), new NumberNode(3),
new NumberNode(4), new NumberNode(5), new NumberNode(6), new NumberNode(7),
new NumberNode(8), new NumberNode(9), new NumberNode(10), new NumberNode(11),
new NumberNode(12), new NumberNode(13), new NumberNode(14), new NumberNode(15),
new NumberNode(16), new NumberNode(17), new NumberNode(18), new NumberNode(19),
new NumberNode(20), new NumberNode(21), new NumberNode(22), new NumberNode(23),
new NumberNode(24), new NumberNode(25), new NumberNode(26), new NumberNode(27),
new NumberNode(28), new NumberNode(29), new NumberNode(30), new NumberNode(31),
};
private readonly Lazy<double> value;
private NumberNode(ArraySegment<byte> bufferedToken)
: base(JsonNodeType.Number)
{
this.value = new Lazy<double>(() => JsonTextUtil.GetNumberValue(bufferedToken));
}
private NumberNode(double value)
: base(JsonNodeType.Number)
{
this.value = new Lazy<double>(() => value);
}
public double Value
{
get
{
return this.value.Value;
}
}
public static NumberNode Create(ArraySegment<byte> bufferedToken)
{
IReadOnlyList<byte> payload = bufferedToken;
if (payload.Count == 1 && payload[0] >= '0' && payload[0] <= '9')
{
// Single digit number.
return NumberNode.LiteralNumberNodes[payload[0] - '0'];
}
if (payload.Count == 2 && payload[0] >= '0' && payload[0] <= '9' && payload[1] >= '0' && payload[1] <= '9')
{
// Two digit number.
int index = ((payload[0] - '0') * 10) + (payload[1] - '0');
if (index >= 0 && index < NumberNode.LiteralNumberNodes.Length)
{
return NumberNode.LiteralNumberNodes[index];
}
}
return new NumberNode(bufferedToken);
}
}
private sealed class ObjectNode : JsonTextNode
{
private static readonly ObjectNode Empty = new ObjectNode(new List<ObjectProperty>());
private readonly List<ObjectProperty> properties;
private ObjectNode(List<ObjectProperty> properties)
: base(JsonNodeType.Object)
{
this.properties = properties;
}
public IReadOnlyList<ObjectProperty> Properties
{
get { return this.properties; }
}
public static ObjectNode Create(List<ObjectProperty> properties)
{
if (properties.Count == 0)
{
return ObjectNode.Empty;
}
return new ObjectNode(properties);
}
}
private sealed class StringNode : StringNodeBase
{
private static readonly StringNode Empty = new StringNode(string.Empty);
private StringNode(ArraySegment<byte> bufferedToken)
: base(bufferedToken, true)
{
}
private StringNode(string value)
: base(value, true)
{
}
public static StringNode Create(ArraySegment<byte> bufferedToken)
{
if (bufferedToken.Count == 0)
{
return StringNode.Empty;
}
// In the future we can have a flyweight dictionary for system strings.
return new StringNode(bufferedToken);
}
}
private abstract class StringNodeBase : JsonTextNode
{
private readonly Lazy<string> value;
protected StringNodeBase(ArraySegment<byte> bufferedToken, bool isStringNode)
: base(isStringNode ? JsonNodeType.String : JsonNodeType.FieldName)
{
this.value = new Lazy<string>(() => JsonTextUtil.GetStringValue(bufferedToken));
}
protected StringNodeBase(string value, bool isStringNode)
: base(isStringNode ? JsonNodeType.String : JsonNodeType.FieldName)
{
this.value = new Lazy<string>(() => value);
}
public string Value
{
get { return this.value.Value; }
}
}
private sealed class TrueNode : JsonTextNode
{
private static readonly TrueNode Instance = new TrueNode();
private TrueNode()
: base(JsonNodeType.True)
{
}
public static TrueNode Create()
{
return TrueNode.Instance;
}
}
#endregion
}
}
}

Просмотреть файл

@ -0,0 +1,144 @@
//-----------------------------------------------------------------------
// <copyright file="JsonNavigator.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
/// <summary>
/// Base abstract class for JSON navigators.
/// The navigator defines methods that allow random access to JSON document nodes.
/// </summary>
internal abstract partial class JsonNavigator : IJsonNavigator
{
/// <summary>
/// Initializes a new instance of the <see cref="JsonNavigator"/> class.
/// </summary>
protected JsonNavigator()
{
}
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the IJsonNavigator.
/// </summary>
public abstract JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Creates a JsonNavigator that can navigate a supplied buffer
/// </summary>
/// <param name="buffer">The buffer to navigate</param>
/// <param name="skipValidation">Whether validation should be skipped.</param>
/// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns>
public static IJsonNavigator Create(byte[] buffer, bool skipValidation = false)
{
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
// Examine the first buffer byte to determine the serialization format
byte firstByte = buffer[0];
switch ((JsonSerializationFormat)firstByte)
{
// Explicitly pick from the set of supported formats
case JsonSerializationFormat.Binary:
return new JsonBinaryNavigator(buffer, skipValidation);
default:
// or otherwise assume text format
return new JsonTextNavigator(buffer, skipValidation);
}
}
/// <summary>
/// Gets <see cref="IJsonNavigatorNode"/> of the root node.
/// </summary>
/// <returns><see cref="IJsonNavigatorNode"/> corresponding to the root node.</returns>
public abstract IJsonNavigatorNode GetRootNode();
/// <summary>
/// Gets the <see cref="JsonNodeType"/> type for a particular node
/// </summary>
/// <param name="node">The <see cref="IJsonNavigatorNode"/> of the node you want to know the type of</param>
/// <returns><see cref="JsonNodeType"/> for the node</returns>
public abstract JsonNodeType GetNodeType(IJsonNavigatorNode node);
/// <summary>
/// Gets the numeric value for a node
/// </summary>
/// <param name="numberNode">The <see cref="IJsonNavigatorNode"/> of the node you want the number value from.</param>
/// <returns>A double that represents the number value in the node.</returns>
public abstract double GetNumberValue(IJsonNavigatorNode numberNode);
/// <summary>
/// Tries to get the buffered string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the buffered string from.</param>
/// <param name="bufferedStringValue">The buffered string value if possible</param>
/// <returns><code>true</code> if the JsonNavigator successfully got the buffered string value; <code>false</code> if the JsonNavigator failed to get the buffered string value.</returns>
public abstract bool TryGetBufferedStringValue(IJsonNavigatorNode stringNode, out IReadOnlyList<byte> bufferedStringValue);
/// <summary>
/// Gets a string value from a node.
/// </summary>
/// <param name="stringNode">The <see cref="IJsonNavigatorNode"/> of the node to get the string value from.</param>
/// <returns>The string value from the node.</returns>
public abstract string GetStringValue(IJsonNavigatorNode stringNode);
/// <summary>
/// Gets the number of elements in an array node.
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to get the count of.</param>
/// <returns>The number of elements in the array node.</returns>
public abstract int GetArrayItemCount(IJsonNavigatorNode arrayNode);
/// <summary>
/// Gets the node at a particular index of an array node
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the (array) node to index from.</param>
/// <param name="index">The offset into the array</param>
/// <returns>The <see cref="IJsonNavigatorNode"/> of the node at a particular index of an array node</returns>
public abstract IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNode, int index);
/// <summary>
/// Gets an IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.
/// </summary>
/// <param name="arrayNode">The <see cref="IJsonNavigatorNode"/> of the array to get the items from</param>
/// <returns>The IEnumerable of <see cref="IJsonNavigatorNode"/>s for an arrayNode.</returns>
public abstract IEnumerable<IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNode);
/// <summary>
/// Gets the number of properties in an object node.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of node to get the property count from.</param>
/// <returns>The number of properties in an object node.</returns>
public abstract int GetObjectPropertyCount(IJsonNavigatorNode objectNode);
/// <summary>
/// Tries to get a object property from an object with a particular property name.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of object node to get a property from.</param>
/// <param name="propertyName">The name of the property to search for.</param>
/// <param name="objectProperty">The <see cref="ObjectProperty"/> with the specified property name if it exists.</param>
/// <returns><code>true</code> if the JsonNavigator successfully found the <see cref="IJsonNavigatorNode"/> with the specified property name; <code>false</code> otherwise.</returns>
public abstract bool TryGetObjectProperty(IJsonNavigatorNode objectNode, string propertyName, out ObjectProperty objectProperty);
/// <summary>
/// Gets an IEnumerable of <see cref="ObjectProperty"/> properties from an object node.
/// </summary>
/// <param name="objectNode">The <see cref="IJsonNavigatorNode"/> of object node to get the properties from.</param>
/// <returns>The IEnumerable of <see cref="ObjectProperty"/> properties from an object node.</returns>
public abstract IEnumerable<ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNode);
/// <summary>
/// Tries to get the buffered raw json
/// </summary>
/// <param name="jsonNode">The json node of interest</param>
/// <param name="bufferedRawJson">The raw json.</param>
/// <returns>True if bufferedRawJson was set. False otherwise.</returns>
public abstract bool TryGetBufferedRawJson(IJsonNavigatorNode jsonNode, out IReadOnlyList<byte> bufferedRawJson);
}
}

Просмотреть файл

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------
// <copyright file="JsonNodeType.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
/// <summary>
/// The enumeration of JSON node types
/// </summary>
internal enum JsonNodeType
{
/// <summary>
/// Corresponds to the 'null' value in JSON.
/// </summary>
Null,
/// <summary>
/// Corresponds to the 'false' value in JSON.
/// </summary>
False,
/// <summary>
/// Corresponds to the 'true' value in JSON.
/// </summary>
True,
/// <summary>
/// Corresponds to the number type in JSON (number = [ minus ] integer [ fraction ] [ exponent ])
/// </summary>
Number,
/// <summary>
/// Corresponds to the string type in JSON (string = quotation-mark *char quotation-mark)
/// </summary>
String,
/// <summary>
/// Corresponds to the array type in JSON ( begin-array [ value *( value-separator value ) ] end-array)
/// </summary>
Array,
/// <summary>
/// Corresponds to the object type in JSON (begin-object [ member *( value-separator member ) ] end-object)
/// </summary>
Object,
/// <summary>
/// Corresponds to the property name of a JSON object property (which is also a string).
/// </summary>
FieldName,
/// <summary>
/// Unknown JsonNodeType.
/// </summary>
Unknown,
}
}

Просмотреть файл

@ -0,0 +1,344 @@
//-----------------------------------------------------------------------
// <copyright file="JsonObjectState.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Azure.Documents;
/// <summary>
/// This class maintains the current state of a JSON object/value while it is being read or written.
/// </summary>
internal sealed class JsonObjectState
{
/// <summary>
/// This constant defines the maximum nesting depth that the parser supports.
/// The JSON spec states that this is an implementation dependent thing, so we're just picking a value for now.
/// FWIW .Net chose 100
/// Note: This value needs to be a multiple of 8 and must be less than 2^15 (see asserts in the constructor)
/// </summary>
private const int JsonMaxNestingDepth = 128;
/// <summary>
/// Flag for determining whether to throw exceptions that connote a context at the end or not started / complete.
/// </summary>
private readonly bool readMode;
/// <summary>
/// Stores a bitmap for whether we are in an array or object context at a particular level (0 => array, 1 => object).
/// </summary>
private readonly byte[] nestingStackBitmap;
/// <summary>
/// The current nesting stack index.
/// </summary>
private int nestingStackIndex;
/// <summary>
/// The current JsonTokenType.
/// </summary>
private JsonTokenType currentTokenType;
/// <summary>
/// The current JsonObjectContext.
/// </summary>
private JsonObjectContext currentContext;
/// <summary>
/// Initializes a new instance of the JsonObjectState class.
/// </summary>
/// <param name="readMode">Flag for determining whether to throw exceptions that correspond to a JsonReader or JsonWriter.</param>
public JsonObjectState(bool readMode)
{
Debug.Assert(JsonMaxNestingDepth % 8 == 0, "JsonMaxNestingDepth must be multiple of 8");
Debug.Assert(JsonMaxNestingDepth < (1 << 15), "JsonMaxNestingDepth must be less than 2^15");
this.readMode = readMode;
this.nestingStackBitmap = new byte[JsonMaxNestingDepth / 8];
this.nestingStackIndex = -1;
this.currentTokenType = JsonTokenType.NotStarted;
this.currentContext = JsonObjectContext.None;
}
/// <summary>
/// JsonObjectContext enum
/// </summary>
private enum JsonObjectContext
{
/// <summary>
/// Context at the start of the object state.
/// </summary>
None,
/// <summary>
/// Context when state is in an array.
/// </summary>
Array,
/// <summary>
/// Context when state is in an object.
/// </summary>
Object,
}
/// <summary>
/// Gets the current depth (level of nesting).
/// </summary>
public int CurrentDepth
{
get
{
return this.nestingStackIndex + 1;
}
}
/// <summary>
/// Gets the current JsonTokenType.
/// </summary>
public JsonTokenType CurrentTokenType
{
get
{
return this.currentTokenType;
}
}
/// <summary>
/// Gets a value indicating whether a property is expected.
/// </summary>
public bool IsPropertyExpected
{
get
{
return (this.currentTokenType != JsonTokenType.FieldName) && (this.currentContext == JsonObjectContext.Object);
}
}
/// <summary>
/// Gets a value indicating whether the current context is an array.
/// </summary>
public bool InArrayContext
{
get
{
return this.currentContext == JsonObjectContext.Array;
}
}
/// <summary>
/// Gets a value indicating whether the current context in an object.
/// </summary>
public bool InObjectContext
{
get
{
return this.currentContext == JsonObjectContext.Object;
}
}
/// <summary>
/// Gets the current JsonObjectContext
/// </summary>
private JsonObjectContext RetrieveCurrentContext
{
get
{
if (this.nestingStackIndex < 0)
{
return JsonObjectContext.None;
}
return (this.nestingStackBitmap[this.nestingStackIndex / 8] & this.Mask) == 0 ? JsonObjectContext.Array : JsonObjectContext.Object;
}
}
/// <summary>
/// Gets a mask to use to get the current context from the nesting stack
/// </summary>
private byte Mask
{
get
{
return (byte)(1 << (this.nestingStackIndex % 8));
}
}
/// <summary>
/// Registers a JsonTokenType.
/// </summary>
/// <param name="jsonTokenType">The JsonTokenType to register.</param>
public void RegisterToken(JsonTokenType jsonTokenType)
{
switch (jsonTokenType)
{
case JsonTokenType.String:
case JsonTokenType.Number:
case JsonTokenType.True:
case JsonTokenType.False:
case JsonTokenType.Null:
this.RegisterValue(jsonTokenType);
break;
case JsonTokenType.BeginArray:
this.RegisterBeginArray();
break;
case JsonTokenType.EndArray:
this.RegisterEndArray();
break;
case JsonTokenType.BeginObject:
this.RegisterBeginObject();
break;
case JsonTokenType.EndObject:
this.RegisterEndObject();
break;
case JsonTokenType.FieldName:
this.RegisterFieldName();
break;
default:
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonTokenType, jsonTokenType));
}
}
/// <summary>
/// Pushes a JsonObjectContext onto the nesting stack.
/// </summary>
/// <param name="isArray">Whether the JsonObjectContext is an array.</param>
private void Push(bool isArray)
{
if (this.nestingStackIndex + 1 >= JsonMaxNestingDepth)
{
throw new InvalidOperationException(RMResources.JsonMaxNestingExceeded);
}
this.nestingStackIndex++;
if (isArray)
{
this.nestingStackBitmap[this.nestingStackIndex / 8] &= (byte)~this.Mask;
this.currentContext = JsonObjectContext.Array;
}
else
{
this.nestingStackBitmap[this.nestingStackIndex / 8] |= this.Mask;
this.currentContext = JsonObjectContext.Object;
}
}
/// <summary>
/// Registers any json token type.
/// </summary>
/// <param name="jsonTokenType">The jsonTokenType to register</param>
private void RegisterValue(JsonTokenType jsonTokenType)
{
if ((this.currentContext == JsonObjectContext.Object) && (this.currentTokenType != JsonTokenType.FieldName))
{
throw new JsonMissingPropertyException();
}
if ((this.currentContext == JsonObjectContext.None) && (this.currentTokenType != JsonTokenType.NotStarted))
{
throw new JsonPropertyArrayOrObjectNotStartedException();
}
this.currentTokenType = jsonTokenType;
}
/// <summary>
/// Registers a beginning of a json array ('[')
/// </summary>
private void RegisterBeginArray()
{
// An array start is also a value
this.RegisterValue(JsonTokenType.BeginArray);
this.Push(true);
}
/// <summary>
/// Registers the end of a json array (']')
/// </summary>
private void RegisterEndArray()
{
if (this.currentContext != JsonObjectContext.Array)
{
if (this.readMode)
{
throw new JsonUnexpectedEndArrayException();
}
else
{
throw new JsonArrayNotStartedException();
}
}
this.nestingStackIndex--;
this.currentTokenType = JsonTokenType.EndArray;
this.currentContext = this.RetrieveCurrentContext;
}
/// <summary>
/// Registers a beginning of a json object ('{')
/// </summary>
private void RegisterBeginObject()
{
// An object start is also a value
this.RegisterValue(JsonTokenType.BeginObject);
this.Push(false);
}
/// <summary>
/// Registers a end of a json object ('}')
/// </summary>
private void RegisterEndObject()
{
if (this.currentContext != JsonObjectContext.Object)
{
if (this.readMode)
{
throw new JsonUnexpectedEndObjectException();
}
else
{
throw new JsonObjectNotStartedException();
}
}
// check if we have a property name but not a value
if (this.currentTokenType == JsonTokenType.FieldName)
{
if (this.readMode)
{
throw new JsonUnexpectedEndObjectException();
}
else
{
throw new JsonNotCompleteException();
}
}
this.nestingStackIndex--;
this.currentTokenType = JsonTokenType.EndObject;
this.currentContext = this.RetrieveCurrentContext;
}
/// <summary>
/// Register a Json FieldName
/// </summary>
private void RegisterFieldName()
{
if (this.currentContext != JsonObjectContext.Object)
{
throw new JsonObjectNotStartedException();
}
if (this.currentTokenType == JsonTokenType.FieldName)
{
throw new JsonPropertyAlreadyAddedException();
}
this.currentTokenType = JsonTokenType.FieldName;
}
}
}

Просмотреть файл

@ -0,0 +1,403 @@
//-----------------------------------------------------------------------
// <copyright file="JsonParseException.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System.Net;
using Microsoft.Azure.Documents;
/// <summary>
/// Abstract class that all JsonParseExceptions will derive from.
/// </summary>
internal abstract class JsonParseException : DocumentClientException
{
/// <summary>
/// Initializes a new instance of the JsonParseException class.
/// </summary>
/// <param name="message">The exception message for the JsonParseException</param>
protected JsonParseException(string message)
: base(message, null, HttpStatusCode.BadRequest)
{
}
}
/// <summary>
/// JsonParseException for MissingClosingQuote
/// </summary>
internal sealed class JsonMissingClosingQuoteException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMissingClosingQuoteException class.
/// </summary>
public JsonMissingClosingQuoteException()
: base(RMResources.JsonMissingClosingQuote)
{
}
}
/// <summary>
/// JsonParseException for NotFieldnameToken
/// </summary>
internal sealed class JsonNotFieldnameTokenException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNotFieldnameTokenException class.
/// </summary>
public JsonNotFieldnameTokenException()
: base(RMResources.JsonNotFieldnameToken)
{
}
}
/// <summary>
/// JsonParseException for InvalidParameter
/// </summary>
internal sealed class JsonInvalidParameterException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidParameterException class.
/// </summary>
public JsonInvalidParameterException()
: base(RMResources.JsonInvalidParameter)
{
}
}
/// <summary>
/// JsonParseException for NumberTooLong
/// </summary>
internal sealed class JsonNumberTooLongException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNumberTooLongException class.
/// </summary>
public JsonNumberTooLongException()
: base(RMResources.JsonNumberTooLong)
{
}
}
/// <summary>
/// JsonParseException for MissingNameSeparator
/// </summary>
internal sealed class JsonMissingNameSeparatorException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMissingNameSeparatorException class.
/// </summary>
public JsonMissingNameSeparatorException()
: base(RMResources.JsonMissingNameSeparator)
{
}
}
/// <summary>
/// JsonParseException for UnexpectedToken
/// </summary>
internal sealed class JsonUnexpectedTokenException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonUnexpectedTokenException class.
/// </summary>
public JsonUnexpectedTokenException()
: base(RMResources.JsonUnexpectedToken)
{
}
}
/// <summary>
/// JsonParseException for UnexpectedEndArray
/// </summary>
internal sealed class JsonUnexpectedEndArrayException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonUnexpectedEndArrayException class.
/// </summary>
public JsonUnexpectedEndArrayException()
: base(RMResources.JsonUnexpectedEndArray)
{
}
}
/// <summary>
/// JsonParseException for UnexpectedEndObject
/// </summary>
internal sealed class JsonUnexpectedEndObjectException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonUnexpectedEndObjectException class.
/// </summary>
public JsonUnexpectedEndObjectException()
: base(RMResources.JsonUnexpectedEndObject)
{
}
}
/// <summary>
/// JsonParseException for InvalidToken
/// </summary>
internal sealed class JsonInvalidTokenException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidTokenException class.
/// </summary>
public JsonInvalidTokenException()
: base(RMResources.JsonInvalidToken)
{
}
}
/// <summary>
/// JsonParseException for UnexpectedNameSeparator
/// </summary>
internal sealed class JsonUnexpectedNameSeparatorException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonUnexpectedNameSeparatorException class.
/// </summary>
public JsonUnexpectedNameSeparatorException()
: base(RMResources.JsonUnexpectedNameSeparator)
{
}
}
/// <summary>
/// JsonParseException for UnexpectedValueSeparator
/// </summary>
internal sealed class JsonUnexpectedValueSeparatorException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonUnexpectedValueSeparatorException class.
/// </summary>
public JsonUnexpectedValueSeparatorException()
: base(RMResources.JsonUnexpectedValueSeparator)
{
}
}
/// <summary>
/// JsonParseException for MissingEndObject
/// </summary>
internal sealed class JsonMissingEndObjectException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMissingEndObjectException class.
/// </summary>
public JsonMissingEndObjectException()
: base(RMResources.JsonMissingEndObject)
{
}
}
/// <summary>
/// JsonParseException for MissingEndArray
/// </summary>
internal sealed class JsonMissingEndArrayException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMissingEndArrayException class.
/// </summary>
public JsonMissingEndArrayException()
: base(RMResources.JsonMissingEndArray)
{
}
}
/// <summary>
/// JsonParseException for NotStringToken
/// </summary>
internal sealed class JsonNotStringTokenException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNotStringTokenException class.
/// </summary>
public JsonNotStringTokenException()
: base(RMResources.JsonNotStringToken)
{
}
}
/// <summary>
/// JsonParseException for MaxNestingExceeded
/// </summary>
internal sealed class JsonMaxNestingExceededException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMaxNestingExceededException class.
/// </summary>
public JsonMaxNestingExceededException()
: base(RMResources.JsonMaxNestingExceeded)
{
}
}
/// <summary>
/// JsonParseException for InvalidEscapedCharacter
/// </summary>
internal sealed class JsonInvalidEscapedCharacterException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidEscapedCharacterException class.
/// </summary>
public JsonInvalidEscapedCharacterException()
: base(RMResources.JsonInvalidEscapedCharacter)
{
}
}
/// <summary>
/// JsonParseException for InvalidUnicodeEscape
/// </summary>
internal sealed class JsonInvalidUnicodeEscapeException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidUnicodeEscapeException class.
/// </summary>
public JsonInvalidUnicodeEscapeException()
: base(RMResources.JsonInvalidUnicodeEscape)
{
}
}
/// <summary>
/// JsonParseException for InvalidStringCharacter
/// </summary>
internal sealed class JsonInvalidStringCharacterException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidStringCharacterException class.
/// </summary>
public JsonInvalidStringCharacterException()
: base(RMResources.JsonInvalidStringCharacter)
{
}
}
/// <summary>
/// JsonParseException for InvalidNumber
/// </summary>
internal sealed class JsonInvalidNumberException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonInvalidNumberException class.
/// </summary>
public JsonInvalidNumberException()
: base(RMResources.JsonInvalidNumber)
{
}
}
/// <summary>
/// JsonParseException for NotNumberToken
/// </summary>
internal sealed class JsonNotNumberTokenException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNotNumberTokenException class.
/// </summary>
public JsonNotNumberTokenException()
: base(RMResources.JsonNotNumberToken)
{
}
}
/// <summary>
/// JsonParseException for NumberOutOfRange
/// </summary>
internal sealed class JsonNumberOutOfRangeException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNumberOutOfRangeException class.
/// </summary>
public JsonNumberOutOfRangeException()
: base(RMResources.JsonNumberOutOfRange)
{
}
}
/// <summary>
/// JsonParseException for MissingProperty
/// </summary>
internal sealed class JsonMissingPropertyException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonMissingPropertyException class.
/// </summary>
public JsonMissingPropertyException()
: base(RMResources.JsonMissingProperty)
{
}
}
/// <summary>
/// JsonParseException for PropertyAlreadyAdded
/// </summary>
internal sealed class JsonPropertyAlreadyAddedException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonPropertyAlreadyAddedException class.
/// </summary>
public JsonPropertyAlreadyAddedException()
: base(RMResources.JsonPropertyAlreadyAdded)
{
}
}
/// <summary>
/// JsonParseException for ObjectNotStarted
/// </summary>
internal sealed class JsonObjectNotStartedException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonObjectNotStartedException class.
/// </summary>
public JsonObjectNotStartedException()
: base(RMResources.JsonObjectNotStarted)
{
}
}
/// <summary>
/// JsonParseException for ArrayNotStarted
/// </summary>
internal sealed class JsonArrayNotStartedException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonArrayNotStartedException class.
/// </summary>
public JsonArrayNotStartedException()
: base(RMResources.JsonArrayNotStarted)
{
}
}
/// <summary>
/// JsonParseException for PropertyArrayOrObjectNotStarted
/// </summary>
internal sealed class JsonPropertyArrayOrObjectNotStartedException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonPropertyArrayOrObjectNotStartedException class.
/// </summary>
public JsonPropertyArrayOrObjectNotStartedException()
: base(RMResources.JsonPropertyArrayOrObjectNotStarted)
{
}
}
/// <summary>
/// JsonParseException for NotComplete
/// </summary>
internal sealed class JsonNotCompleteException : JsonParseException
{
/// <summary>
/// Initializes a new instance of the JsonNotCompleteException class.
/// </summary>
public JsonNotCompleteException()
: base(RMResources.JsonNotComplete)
{
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,169 @@
//-----------------------------------------------------------------------
// <copyright file="JsonReader.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// Base abstract class for JSON readers.
/// The reader defines methods that allow for reading a JSON encoded value as a stream of tokens.
/// The tokens are traversed in the same order as they appear in the JSON document.
/// </summary>
internal abstract partial class JsonReader : IJsonReader
{
/// <summary>
/// The <see cref="JsonObjectState"/>
/// </summary>
protected readonly JsonObjectState JsonObjectState;
/// <summary>
/// Whether to skip validation.
/// </summary>
protected readonly bool SkipValidation;
/// <summary>
/// Initializes a new instance of the JsonReader class.
/// </summary>
/// <param name="skipValidation">Whether or not to skip validation.</param>
protected JsonReader(bool skipValidation)
{
this.JsonObjectState = new JsonObjectState(true);
this.SkipValidation = skipValidation;
}
/// <summary>
/// Gets the <see cref="JsonSerializationFormat"/> for the JsonReader
/// </summary>
public abstract JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Gets the current level of nesting of the JSON that the JsonReader is reading.
/// </summary>
public int CurrentDepth
{
get
{
return this.JsonObjectState.CurrentDepth;
}
}
/// <summary>
/// Gets the <see cref="JsonTokenType"/> of the current token that the JsonReader is about to read.
/// </summary>
public JsonTokenType CurrentTokenType
{
get
{
return this.JsonObjectState.CurrentTokenType;
}
}
/// <summary>
/// Creates a JsonReader that can read a supplied stream (assumes UTF-8 encoding).
/// </summary>
/// <param name="stream">the stream to read.</param>
/// <param name="skipvalidation">whether or not to skip validation.</param>
/// <returns>a concrete JsonReader that can read the supplied stream.</returns>
public static IJsonReader Create(Stream stream, bool skipvalidation = false)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
BinaryReader tempBinaryReader = new BinaryReader(stream, Encoding.UTF8);
// examine the first buffer byte to determine the serialization format
byte firstbyte = tempBinaryReader.ReadByte();
// you have to rewind the stream since even "peeking" still reads it into the bufferedstream
stream.Seek(0, SeekOrigin.Begin);
// explicitly pick from the set of supported formats, or otherwise assume text format
switch ((JsonSerializationFormat)firstbyte)
{
case JsonSerializationFormat.Binary:
return new JsonBinaryReader(stream, skipvalidation);
default:
return new JsonTextReader(stream, Encoding.UTF8, skipvalidation);
}
}
/// <summary>
/// Creates a JsonTextReader that can read a supplied stream with the specified encoding.
/// </summary>
/// <param name="stream">The stream to read.</param>
/// <param name="encoding">The encoding of the text (UTF-8, UTF-16 / Unicode, or UTF-32).</param>
/// <param name="skipValidation">Whether or not to skip validation.</param>
/// <returns>A concrete JsonReader that can read the supplied stream.</returns>
public static IJsonReader CreateTextReaderWithEncoding(Stream stream, Encoding encoding, bool skipValidation = false)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
if (encoding != Encoding.UTF8 && encoding != Encoding.Unicode && encoding != Encoding.UTF32)
{
throw new ArgumentException("Json Text only supports UTF8, UTF16/Unicode, or UTF32");
}
return new JsonTextReader(stream, encoding, skipValidation);
}
/// <summary>
/// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding).
/// </summary>
/// <param name="buffer">The byte array to read from.</param>
/// <param name="skipValidation">Whether or not to skip validation.</param>
/// <returns>A concrete JsonReader that can read the supplied byte array.</returns>
public static IJsonReader Create(byte[] buffer, bool skipValidation = false)
{
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
byte firstByte = buffer[0];
// Explicitly pick from the set of supported formats, or otherwise assume text format
switch ((JsonSerializationFormat)firstByte)
{
case JsonSerializationFormat.Binary:
return new JsonBinaryReader(buffer, skipValidation);
default:
return new JsonTextReader(buffer, skipValidation);
}
}
/// <summary>
/// Advances the JsonReader by one token.
/// </summary>
/// <returns><code>true</code> if the JsonReader successfully advanced to the next token; <code>false</code> if the JsonReader has passed the end of the JSON.</returns>
public abstract bool Read();
/// <summary>
/// Gets the next JSON token from the JsonReader as a double.
/// </summary>
/// <returns>The next JSON token from the JsonReader as a double.</returns>
public abstract double GetNumberValue();
/// <summary>
/// Gets the next JSON token from the JsonReader as a string.
/// </summary>
/// <returns>The next JSON token from the JsonReader as a string.</returns>
public abstract string GetStringValue();
/// <summary>
/// Gets next JSON token from the JsonReader as a raw series of bytes that is buffered.
/// </summary>
/// <returns>The next JSON token from the JsonReader as a raw series of bytes that is buffered.</returns>
public abstract IReadOnlyList<byte> GetBufferedRawJsonToken();
}
}

Просмотреть файл

@ -0,0 +1,36 @@
//-----------------------------------------------------------------------
// <copyright file="JsonSerializationFormat.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
/// <summary>
/// Defines JSON different serialization Formats
/// </summary>
/// <remarks>
/// Every enumeration type has an underlying type, which can be any integral type except char.
/// The default underlying type of enumeration elements is integer.
/// To declare an enum of another integral type, such as byte, use a colon after the identifier followed by the type, as shown in the following example.
/// </remarks>
internal enum JsonSerializationFormat : byte
{
/// <summary>
/// Plain text
/// </summary>
Text = 0,
/// <summary>
/// Binary Encoding
/// </summary>
Binary = 128,
/// <summary>
/// HybridRow Binary Encoding
/// </summary>
HybridRow = 129,
// All other format values need to be > 127,
// otherwise a valid JSON starting character (0-9, f[alse], t[rue], n[ull],{,[,") might be interpreted as a serialization format.
}
}

Просмотреть файл

@ -0,0 +1,128 @@
//-----------------------------------------------------------------------
// <copyright file="JsonTextUtil.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Text;
/// <summary>
/// Common utility class for JsonTextReader and JsonTextNavigator.
/// Please treat this class as private.
/// </summary>
internal static class JsonTextUtil
{
/// <summary>
/// Gets the number value from the specified token.
/// </summary>
/// <param name="bufferedToken">The jsonToken returned from that holds the raw number that you want the value of.</param>
/// <returns>The number value from the specified token.</returns>
public static double GetNumberValue(ArraySegment<byte> bufferedToken)
{
byte[] rawBufferedTokenArray = bufferedToken.Array;
int offset = bufferedToken.Offset;
int count = bufferedToken.Count;
string stringDouble = Encoding.UTF8.GetString(rawBufferedTokenArray, offset, count);
return double.Parse(stringDouble);
}
/// <summary>
/// Gets the string value from the specified token.
/// </summary>
/// <param name="bufferedToken">The buffered token.</param>
/// <returns>The string value from the specified token.</returns>
public static string GetStringValue(ArraySegment<byte> bufferedToken)
{
// Offsetting by an additional character and removing 2 from the length since I want to skip the quotes.
ArraySegment<byte> stringToken = new ArraySegment<byte>(bufferedToken.Array, bufferedToken.Offset + 1, bufferedToken.Count - 2);
return JsonTextUtil.UnescapeJson(Encoding.UTF8.GetChars(stringToken.Array, stringToken.Offset, stringToken.Count));
}
/// <summary>
/// Unescapes a json.
/// </summary>
/// <param name="escapedString">The escaped json.</param>
/// <returns>The unescaped json.</returns>
public static string UnescapeJson(char[] escapedString)
{
int readOffset = 0;
int writeOffset = 0;
while (readOffset != escapedString.Length)
{
if (escapedString[readOffset] == '\\')
{
// Consume the '\' character
readOffset++;
// Figure out how to escape.
switch (escapedString[readOffset++])
{
case 'b':
escapedString[writeOffset++] = '\b';
break;
case 'f':
escapedString[writeOffset++] = '\f';
break;
case 'n':
escapedString[writeOffset++] = '\n';
break;
case 'r':
escapedString[writeOffset++] = '\r';
break;
case 't':
escapedString[writeOffset++] = '\t';
break;
case '\\':
escapedString[writeOffset++] = '\\';
break;
case '"':
escapedString[writeOffset++] = '"';
break;
case '/':
escapedString[writeOffset++] = '/';
break;
case 'u':
// parse Json unicode sequence: \uXXXX(\uXXXX)
// Start by reading XXXX. \u is already read.
char unescpaedUnicodeCharacter = (char)0;
for (int sequenceIndex = 0; sequenceIndex < 4; sequenceIndex++)
{
unescpaedUnicodeCharacter <<= 4;
char currentCharacter = escapedString[readOffset++];
if (currentCharacter >= '0' && currentCharacter <= '9')
{
unescpaedUnicodeCharacter += (char)(currentCharacter - '0');
}
else if (currentCharacter >= 'A' && currentCharacter <= 'F')
{
unescpaedUnicodeCharacter += (char)(10 + currentCharacter - 'A');
}
else if (currentCharacter >= 'a' && currentCharacter <= 'f')
{
unescpaedUnicodeCharacter += (char)(10 + currentCharacter - 'a');
}
else
{
throw new JsonInvalidEscapedCharacterException();
}
}
escapedString[writeOffset++] = unescpaedUnicodeCharacter;
break;
}
}
else
{
escapedString[writeOffset++] = escapedString[readOffset++];
}
}
return new string(escapedString, 0, writeOffset);
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="JsonTokenType.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
/// <summary>
/// Enum of JsonTokenType
/// </summary>
internal enum JsonTokenType
{
/// <summary>
/// Reserved for no other value
/// </summary>
NotStarted,
/// <summary>
/// Corresponds to the beginning of a JSON array ('[')
/// </summary>
BeginArray,
/// <summary>
/// Corresponds to the end of a JSON array (']')
/// </summary>
EndArray,
/// <summary>
/// Corresponds to the beginning of a JSON object ('{')
/// </summary>
BeginObject,
/// <summary>
/// Corresponds to the end of a JSON object ('}')
/// </summary>
EndObject,
/// <summary>
/// Corresponds to a JSON string.
/// </summary>
String,
/// <summary>
/// Corresponds to a JSON number.
/// </summary>
Number,
/// <summary>
/// Corresponds to the JSON 'true' value.
/// </summary>
True,
/// <summary>
/// Corresponds to the JSON 'false' value.
/// </summary>
False,
/// <summary>
/// Corresponds to the JSON 'null' value.
/// </summary>
Null,
/// <summary>
/// Corresponds to the JSON fieldname in a JSON object.
/// </summary>
FieldName,
}
}

Просмотреть файл

@ -0,0 +1,578 @@
//-----------------------------------------------------------------------
// <copyright file="JsonWriter.JsonBinaryWriter.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// Partial class for the JsonWriter that has a private JsonTextWriter below.
/// </summary>
internal abstract partial class JsonWriter : IJsonWriter
{
/// <summary>
/// Concrete implementation of <see cref="JsonWriter"/> that knows how to serialize to binary encoding.
/// </summary>
private sealed class JsonBinaryWriter : JsonWriter
{
private const int TypeMarker = 1;
private const int OneByteLength = 1;
private const int OneByteCount = 1;
private const int TwoByteLength = 2;
private const int TwoByteCount = 2;
private const int FourByteLength = 4;
private const int FourByteCount = 4;
/// <summary>
/// Writer used to write fully materialized context to the internal stream.
/// </summary>
private readonly BinaryWriter binaryWriter;
/// <summary>
/// With binary encoding all the json elements are length prefixed,
/// unfortunately the caller of this class only provides what tokens to write.
/// This means that whenever a user call WriteObject/ArrayStart we don't know the length of said object or array
/// until WriteObject/ArrayEnd is invoked.
/// To get around this we reserve some space for the length and write to it when the user supplies the end token.
/// This stack remembers for each nesting level where it begins and how many items it has.
/// </summary>
private readonly Stack<BeginOffsetAndCount> bufferedContexts;
/// <summary>
/// With binary encoding json elements like arrays and object are prefixed with a length in bytes and optionally a count.
/// This flag just determines whether you want to serialize the count, since it's optional and up to the user to make the
/// tradeoff between O(1) .Count() operation as the cost of additional storage.
/// </summary>
private readonly bool serializeCount;
/// <summary>
/// When a user writes an open array or object we reserve this much space for the type marker + length + count
/// And correct it later when they write a close array or object.
/// </summary>
private readonly int reservationSize;
/// <summary>
/// Initializes a new instance of the JsonBinaryWriter class.
/// </summary>
/// <param name="skipValidation">Whether to skip validation on the JsonObjectState.</param>
/// <param name="serializeCount">Whether to serialize the count for object and array typemarkers.</param>
public JsonBinaryWriter(bool skipValidation, bool serializeCount = false)
: base(skipValidation)
{
this.binaryWriter = new BinaryWriter(new MemoryStream());
this.bufferedContexts = new Stack<BeginOffsetAndCount>();
this.serializeCount = serializeCount;
this.reservationSize = TypeMarker + TwoByteLength + (this.serializeCount ? TwoByteCount : 0);
// Write the serialization format as the very first byte
this.binaryWriter.Write((byte)JsonSerializationFormat.Binary);
// Push on the outermost context
this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength));
}
/// <summary>
/// Gets the SerializationFormat of the JsonWriter.
/// </summary>
public override JsonSerializationFormat SerializationFormat
{
get
{
return JsonSerializationFormat.Binary;
}
}
/// <summary>
/// Gets the current length of the internal buffer.
/// </summary>
public override long CurrentLength
{
get
{
this.binaryWriter.Flush();
return this.binaryWriter.BaseStream.Position;
}
}
/// <summary>
/// Writes the object start symbol to internal buffer.
/// </summary>
public override void WriteObjectStart()
{
this.WriterArrayOrObjectStart(false);
}
/// <summary>
/// Writes the object end symbol to the internal buffer.
/// </summary>
public override void WriteObjectEnd()
{
this.WriteArrayOrObjectEnd(false);
}
/// <summary>
/// Writes the array start symbol to the internal buffer.
/// </summary>
public override void WriteArrayStart()
{
this.WriterArrayOrObjectStart(true);
}
/// <summary>
/// Writes the array end token to the internal buffer.
/// </summary>
public override void WriteArrayEnd()
{
this.WriteArrayOrObjectEnd(true);
}
/// <summary>
/// Writes a field name to the the internal buffer.
/// </summary>
/// <param name="fieldName">The name of the field to write.</param>
public override void WriteFieldName(string fieldName)
{
this.WriteFieldNameOrString(true, fieldName);
}
/// <summary>
/// Writes a string to the internal buffer.
/// </summary>
/// <param name="value">The value of the string to write.</param>
public override void WriteStringValue(string value)
{
this.WriteFieldNameOrString(false, value);
}
/// <summary>
/// Writes an integer to the internal buffer.
/// </summary>
/// <param name="value">The value of the integer to write.</param>
public override void WriteIntValue(long value)
{
this.JsonObjectState.RegisterToken(JsonTokenType.Number);
this.WriteIntegerInternal(value);
this.bufferedContexts.Peek().Count++;
}
/// <summary>
/// Writes a number to the internal buffer.
/// </summary>
/// <param name="value">The value of the number to write.</param>
public override void WriteNumberValue(double value)
{
this.JsonObjectState.RegisterToken(JsonTokenType.Number);
// The maximum integer value that can be stored in an IEEE 754 double type w/o losing precision
const double MaxFullPrecisionValue = ((long)1) << 53;
// Check if the number is an integer
double truncatedValue = Math.Floor(value);
if ((truncatedValue == value) && (value >= -MaxFullPrecisionValue) && (value <= MaxFullPrecisionValue))
{
// The number does not have any decimals and fits in a 64-bit value
this.WriteIntegerInternal((long)value);
}
else
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Double);
this.binaryWriter.Write(value);
}
this.bufferedContexts.Peek().Count++;
}
/// <summary>
/// Writes a boolean to the internal buffer.
/// </summary>
/// <param name="value">The value of the boolean to write.</param>
public override void WriteBoolValue(bool value)
{
this.JsonObjectState.RegisterToken(value ? JsonTokenType.True : JsonTokenType.False);
this.binaryWriter.Write(value ? JsonBinaryEncoding.TypeMarker.True : JsonBinaryEncoding.TypeMarker.False);
this.bufferedContexts.Peek().Count++;
}
/// <summary>
/// Writes a null to the internal buffer.
/// </summary>
public override void WriteNullValue()
{
this.JsonObjectState.RegisterToken(JsonTokenType.Null);
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Null);
this.bufferedContexts.Peek().Count++;
}
/// <summary>
/// Gets the result of the JsonWriter.
/// </summary>
/// <returns>The result of the JsonWriter as an array of bytes.</returns>
public override byte[] GetResult()
{
if (this.bufferedContexts.Count > 1)
{
throw new JsonNotCompleteException();
}
this.binaryWriter.Flush();
long bytesWritten = this.CurrentLength;
byte[] result = new byte[bytesWritten];
this.binaryWriter.BaseStream.Seek(0, SeekOrigin.Begin);
if (bytesWritten > int.MaxValue)
{
throw new InvalidOperationException("Can not get back a buffer more than int.MaxValue");
}
this.binaryWriter.BaseStream.Read(result, 0, (int)bytesWritten);
return result;
}
/// <summary>
/// Writes a raw json token to the internal buffer.
/// </summary>
/// <param name="jsonTokenType">The JsonTokenType of the rawJsonToken</param>
/// <param name="rawJsonToken">The raw json token.</param>
protected override void WriteRawJsonToken(JsonTokenType jsonTokenType, IReadOnlyList<byte> rawJsonToken)
{
throw new NotImplementedException();
}
private void WriterArrayOrObjectStart(bool isArray)
{
this.JsonObjectState.RegisterToken(isArray ? JsonTokenType.BeginArray : JsonTokenType.BeginObject);
// Save the start index
this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength));
// Assume 2-byte value length; as such, we need to reserve upto 5 bytes (1 byte type marker, 2 byte length, 2 byte count).
// We'll adjust this as needed when writing the end of the array/object.
this.binaryWriter.Write((byte)0);
this.binaryWriter.Write((ushort)0);
if (this.serializeCount)
{
this.binaryWriter.Write((ushort)0);
}
}
private void WriteArrayOrObjectEnd(bool isArray)
{
this.JsonObjectState.RegisterToken(isArray ? JsonTokenType.EndArray : JsonTokenType.EndObject);
BeginOffsetAndCount nestedContext = this.bufferedContexts.Pop();
// Do some math
int typeMarkerIndex = (int)nestedContext.Offset;
int payloadIndex = typeMarkerIndex + this.reservationSize;
int originalCursor = (int)this.CurrentLength;
int payloadLength = originalCursor - payloadIndex;
int count = (int)nestedContext.Count;
// Figure out what the typemarker and length should be and do any corrections needed
if (count == 0)
{
// Empty object
// Move the cursor back
this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin);
// Write the type marker
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.EmptyArray : JsonBinaryEncoding.TypeMarker.EmptyObject);
}
else if (count == 1)
{
// Single-property object
// Move the buffer back 2 or 4 bytes since we don't need to encode a length
byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer();
Array.Copy(buffer, payloadIndex, buffer, payloadIndex - (TwoByteLength + (this.serializeCount ? TwoByteCount : 0)), payloadLength);
// Move the cursor back
this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin);
// Write the type marker
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.SingleItemArray : JsonBinaryEncoding.TypeMarker.SinglePropertyObject);
// Move the cursor forward
this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + payloadLength, SeekOrigin.Begin);
}
else
{
// Need to figure out how many bytes to encode the length and the count
if (payloadLength <= byte.MaxValue)
{
// 1 byte length - move the buffer back
byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer();
Array.Copy(buffer, payloadIndex, buffer, payloadIndex - (OneByteLength + (this.serializeCount ? OneByteCount : 0)), payloadLength);
// Move the cursor back
this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin);
// Write the type marker
if (this.serializeCount)
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount);
this.binaryWriter.Write((byte)payloadLength);
this.binaryWriter.Write((byte)count);
}
else
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLength : JsonBinaryEncoding.TypeMarker.Object1ByteLength);
this.binaryWriter.Write((byte)payloadLength);
}
// Move the cursor forward
this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + OneByteLength + (this.serializeCount ? OneByteCount : 0) + payloadLength, SeekOrigin.Begin);
}
else if (payloadLength <= ushort.MaxValue)
{
// 2 byte length - don't need to move the buffer
// Move the cursor back
this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin);
// Write the type marker
if (this.serializeCount)
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount);
this.binaryWriter.Write((ushort)payloadLength);
this.binaryWriter.Write((ushort)count);
}
else
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLength : JsonBinaryEncoding.TypeMarker.Object2ByteLength);
this.binaryWriter.Write((ushort)payloadLength);
}
// Move the cursor forward
this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + TwoByteLength + (this.serializeCount ? TwoByteCount : 0) + payloadLength, SeekOrigin.Begin);
}
else
{
// (payloadLength <= uint.MaxValue)
// 4 byte length - make space for an extra 2 byte length (and 2 byte count)
this.binaryWriter.Write((ushort)0);
if (this.serializeCount)
{
this.binaryWriter.Write((ushort)0);
}
// Move the buffer forward
byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer();
Array.Copy(buffer, payloadIndex, buffer, payloadIndex + TwoByteLength + (this.serializeCount ? TwoByteCount : 0), payloadLength);
// Move the cursor back
this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin);
// Write the type marker
if (this.serializeCount)
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount);
this.binaryWriter.Write((uint)payloadLength);
this.binaryWriter.Write((uint)count);
}
else
{
this.binaryWriter.Write(
isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLength : JsonBinaryEncoding.TypeMarker.Object4ByteLength);
this.binaryWriter.Write((uint)payloadLength);
}
// Move the cursor forward
this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + FourByteLength + (this.serializeCount ? FourByteCount : 0) + payloadLength, SeekOrigin.Begin);
}
}
this.bufferedContexts.Peek().Count++;
}
private bool TryGetEncodedStringTypeMarker(string value, out JsonBinaryEncoding.MultiByteTypeMarker typeMarker)
{
if (this.TryGetEncodedSystemStringTypeMarker(value, out typeMarker))
{
return true;
}
if (this.TryGetEncodedUserStringTypeMarker(value, out typeMarker))
{
return true;
}
return false;
}
private bool TryGetEncodedUserStringTypeMarker(string value, out JsonBinaryEncoding.MultiByteTypeMarker typeMarker)
{
typeMarker = new JsonBinaryEncoding.MultiByteTypeMarker();
return false;
}
private bool TryGetEncodedSystemStringTypeMarker(string value, out JsonBinaryEncoding.MultiByteTypeMarker typeMarker)
{
typeMarker = new JsonBinaryEncoding.MultiByteTypeMarker(null);
int systemStringId;
if (JsonBinaryEncoding.TryGetSystemStringId(value, out systemStringId))
{
const byte OneByteCount = JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMax - JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin;
if (systemStringId < OneByteCount)
{
byte[] typeMarkerBytes = new byte[]
{
(byte)(JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin + (int)systemStringId)
};
typeMarker = new JsonBinaryEncoding.MultiByteTypeMarker(typeMarkerBytes);
}
else
{
int twoByteOffset = ((int)systemStringId) - OneByteCount;
byte[] typeMarkerBytes = new byte[]
{
(byte)((twoByteOffset / 0xFF) + JsonBinaryEncoding.TypeMarker.SystemString2ByteLengthMin),
(byte)(twoByteOffset % 0xFF),
};
typeMarker = new JsonBinaryEncoding.MultiByteTypeMarker(typeMarkerBytes);
}
return true;
}
return false;
}
private void WriteFieldNameOrString(bool isFieldName, string value)
{
this.JsonObjectState.RegisterToken(isFieldName ? JsonTokenType.FieldName : JsonTokenType.String);
JsonBinaryEncoding.MultiByteTypeMarker multiByteTypeMarker;
if (this.TryGetEncodedStringTypeMarker(value, out multiByteTypeMarker))
{
foreach (byte byteValue in multiByteTypeMarker.Values)
{
this.binaryWriter.Write(byteValue);
}
}
else
{
byte[] utf8String = Encoding.UTF8.GetBytes(value);
// See if the string length can be encoded into a single type marker
byte typeMarker = JsonBinaryEncoding.TypeMarker.GetEncodedStringLengthTypeMarker(utf8String.Length);
if (JsonBinaryEncoding.TypeMarker.IsValid(typeMarker))
{
this.binaryWriter.Write(typeMarker);
}
else
{
// Just write the type marker and the corresponding length
if (utf8String.Length < byte.MaxValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String1ByteLength);
this.binaryWriter.Write((byte)utf8String.Length);
}
else if (utf8String.Length < ushort.MaxValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String2ByteLength);
this.binaryWriter.Write((ushort)utf8String.Length);
}
else
{
// (utf8String.Length < uint.MaxValue)
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String4ByteLength);
this.binaryWriter.Write((uint)utf8String.Length);
}
}
// Finally write the string itself.
this.binaryWriter.Write(utf8String);
}
if (!isFieldName)
{
// If we just wrote a string then increment the count (we don't increment for field names, since we need to wait for the corresponding property value).
this.bufferedContexts.Peek().Count++;
}
}
private void WriteIntegerInternal(long value)
{
if (JsonBinaryEncoding.TypeMarker.IsEncodedIntegerLiteral(value))
{
this.binaryWriter.Write((byte)(JsonBinaryEncoding.TypeMarker.LiteralIntMin + value));
}
else
{
if (value >= 0)
{
// Non-negative Number
if (value <= byte.MaxValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.UInt8);
this.binaryWriter.Write((byte)value);
}
else if (value <= short.MaxValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int16);
this.binaryWriter.Write((short)value);
}
else if (value <= int.MaxValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int32);
this.binaryWriter.Write((int)value);
}
else
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int64);
this.binaryWriter.Write((long)value);
}
}
else
{
// Negative Number
if (value < int.MinValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int64);
this.binaryWriter.Write((long)value);
}
else if (value < short.MinValue)
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int32);
this.binaryWriter.Write((int)value);
}
else
{
this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int16);
this.binaryWriter.Write((short)value);
}
}
}
}
private sealed class BeginOffsetAndCount
{
public BeginOffsetAndCount(long offset)
{
this.Offset = offset;
this.Count = 0;
}
public long Offset { get; }
public long Count { get; set; }
}
}
}
}

Просмотреть файл

@ -0,0 +1,432 @@
//-----------------------------------------------------------------------
// <copyright file="JsonWriter.JsonTextWriter.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// Partial class for the JsonWriter that has a private JsonTextWriter below.
/// </summary>
internal abstract partial class JsonWriter : IJsonWriter
{
/// <summary>
/// This class is used to build a JSON string.
/// It supports our defined IJsonWriter interface.
/// It keeps an stack to keep track of scope, and provides error checking using that.
/// It has few other variables for error checking
/// The user can also provide initial size to reserve string buffer, that will help reduce cost of reallocation.
/// It provides error checking based on JSON grammar. It provides escaping for nine characters specified in JSON.
/// </summary>
private sealed class JsonTextWriter : JsonWriter
{
private const char ValueSeperatorToken = ':';
private const char MemberSeperatorToken = ',';
private const char ObjectStartToken = '{';
private const char ObjectEndToken = '}';
private const char ArrayStartToken = '[';
private const char ArrayEndToken = ']';
private const char PropertyStartToken = '"';
private const char PropertyEndToken = '"';
private const char StringStartToken = '"';
private const char StringEndToken = '"';
private const string NotANumber = "NaN";
private const string PositiveInfinity = "Infinity";
private const string NegativeInfinity = "-Infinity";
private const string TrueString = "true";
private const string FalseString = "false";
private const string NullString = "null";
private static readonly Dictionary<Encoding, string> ByteOrderMarkDictionary = new Dictionary<Encoding, string>
{
{ Encoding.UTF8, "\xEF\xBB\xBF" },
{ Encoding.Unicode, "\xFF\xFE" },
{ Encoding.UTF32, "\xFF\xFE\x00\x00" },
};
/// <summary>
/// The internal StreamWriter
/// </summary>
private readonly StreamWriter streamWriter;
/// <summary>
/// Whether we are writing the first value of an array or object
/// </summary>
private bool firstValue;
/// <summary>
/// Initializes a new instance of the JsonTextWriter class.
/// </summary>
/// <param name="encoding">The encoding to use.</param>
/// <param name="skipValidation">Whether or not to skip validation</param>
public JsonTextWriter(Encoding encoding, bool skipValidation)
: base(skipValidation)
{
this.firstValue = true;
this.streamWriter = new StreamWriter(new MemoryStream(), encoding);
}
/// <summary>
/// Gets the SerializationFormat of the JsonWriter.
/// </summary>
public override JsonSerializationFormat SerializationFormat
{
get
{
return JsonSerializationFormat.Text;
}
}
/// <summary>
/// Gets the current length of the internal buffer.
/// </summary>
public override long CurrentLength
{
get
{
return this.streamWriter.BaseStream.Position;
}
}
/// <summary>
/// Writes the object start symbol to internal buffer.
/// </summary>
public override void WriteObjectStart()
{
this.JsonObjectState.RegisterToken(JsonTokenType.BeginObject);
this.PrefixMemberSeparator();
this.WriteChar(ObjectStartToken);
this.firstValue = true;
}
/// <summary>
/// Writes the object end symbol to the internal buffer.
/// </summary>
public override void WriteObjectEnd()
{
this.JsonObjectState.RegisterToken(JsonTokenType.EndObject);
this.WriteChar(ObjectEndToken);
// We reset firstValue here because we'll need a separator before the next value
this.firstValue = false;
}
/// <summary>
/// Writes the array start symbol to the internal buffer.
/// </summary>
public override void WriteArrayStart()
{
this.JsonObjectState.RegisterToken(JsonTokenType.BeginArray);
this.PrefixMemberSeparator();
this.WriteChar(ArrayStartToken);
this.firstValue = true;
}
/// <summary>
/// Writes the array end symbol to the internal buffer.
/// </summary>
public override void WriteArrayEnd()
{
this.JsonObjectState.RegisterToken(JsonTokenType.EndArray);
this.WriteChar(ArrayEndToken);
// We reset firstValue here because we'll need a separator before the next value
this.firstValue = false;
}
/// <summary>
/// Writes a field name to the the internal buffer.
/// </summary>
/// <param name="fieldName">The name of the field to write.</param>
public override void WriteFieldName(string fieldName)
{
this.JsonObjectState.RegisterToken(JsonTokenType.FieldName);
this.PrefixMemberSeparator();
// no separator after property name
this.firstValue = true;
this.WriteChar(PropertyStartToken);
this.WriteEscapedStringToStreamWriter(fieldName, this.streamWriter);
this.WriteChar(PropertyEndToken);
this.WriteChar(ValueSeperatorToken);
}
/// <summary>
/// Writes a string to the internal buffer.
/// </summary>
/// <param name="value">The value of the string to write.</param>
public override void WriteStringValue(string value)
{
this.JsonObjectState.RegisterToken(JsonTokenType.String);
this.PrefixMemberSeparator();
this.WriteChar(StringStartToken);
this.WriteEscapedStringToStreamWriter(value, this.streamWriter);
this.WriteChar(StringEndToken);
}
/// <summary>
/// Writes an integer to the internal buffer.
/// </summary>
/// <param name="value">The value of the integer to write.</param>
public override void WriteIntValue(long value)
{
this.JsonObjectState.RegisterToken(JsonTokenType.Number);
this.PrefixMemberSeparator();
this.streamWriter.Write(value.ToString());
}
/// <summary>
/// Writes a number to the internal buffer.
/// </summary>
/// <param name="value">The value of the number to write.</param>
public override void WriteNumberValue(double value)
{
// The maximum integer value that can be stored in an IEEE 754 double type w/o losing precision
const double MaxFullPrecisionValue = ((long)1) << 53;
// Check if the number is an integer
double truncatedValue = Math.Floor(value);
if ((truncatedValue == value) && (value >= -MaxFullPrecisionValue) && (value <= MaxFullPrecisionValue))
{
// The number does not have any decimals and fits in a 64-bit value
this.WriteIntValue((long)value);
return;
}
this.JsonObjectState.RegisterToken(JsonTokenType.Number);
this.PrefixMemberSeparator();
if (double.IsNaN(value))
{
this.WriteChar(StringStartToken);
this.streamWriter.Write(NotANumber);
this.WriteChar(StringEndToken);
}
else if (double.IsNegativeInfinity(value))
{
this.WriteChar(StringStartToken);
this.streamWriter.Write(NegativeInfinity);
this.WriteChar(StringEndToken);
}
else if (double.IsPositiveInfinity(value))
{
this.WriteChar(StringStartToken);
this.streamWriter.Write(PositiveInfinity);
this.WriteChar(StringEndToken);
}
else
{
// If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision,
// or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
// In some cases, Double values formatted with the "R" standard numeric format string do not successfully round-trip if compiled using the /platform:x64 or /platform:anycpu switches and run on 64-bit systems. To work around this problem, you can format Double values by using the "G17" standard numeric format string.
this.streamWriter.Write(value.ToString("R"));
}
}
/// <summary>
/// Writes a boolean to the internal buffer.
/// </summary>
/// <param name="value">The value of the boolean to write.</param>
public override void WriteBoolValue(bool value)
{
this.JsonObjectState.RegisterToken(value ? JsonTokenType.True : JsonTokenType.False);
this.PrefixMemberSeparator();
if (value)
{
this.streamWriter.Write(TrueString);
}
else
{
this.streamWriter.Write(FalseString);
}
}
/// <summary>
/// Writes a null to the internal buffer.
/// </summary>
public override void WriteNullValue()
{
this.JsonObjectState.RegisterToken(JsonTokenType.Null);
this.PrefixMemberSeparator();
this.streamWriter.Write(NullString);
}
/// <summary>
/// Gets the result of the JsonWriter.
/// </summary>
/// <returns>The result of the JsonWriter as an array of bytes.</returns>
public override byte[] GetResult()
{
// Flush the stream
this.streamWriter.Flush();
// Create a binaryreader to read from the stream
BinaryReader binaryReader = new BinaryReader(this.streamWriter.BaseStream);
// Figure out how many bytes have been written
long bytesWritten = this.CurrentLength;
// Seek to the begining but skip the byte order mark
int byteOrderMarkLength = JsonTextWriter.ByteOrderMarkDictionary[this.streamWriter.Encoding].Length;
this.streamWriter.BaseStream.Seek(byteOrderMarkLength, SeekOrigin.Begin);
// Read the entire steam
return binaryReader.ReadBytes((int)(bytesWritten - byteOrderMarkLength));
}
/// <summary>
/// Gets the result of all the writes as a string.
/// </summary>
/// <returns>The result of all the writes as a string.</returns>
public string GetStringResult()
{
// Flush the stream
this.streamWriter.Flush();
// Create a stream reader to read from the stream
StreamReader streamReader = new StreamReader(
this.streamWriter.BaseStream,
this.streamWriter.Encoding);
// Seek to the begining
this.streamWriter.BaseStream.Seek(0, SeekOrigin.Begin);
// Read the entire stream
string stringResult = streamReader.ReadToEnd();
return stringResult;
}
/// <summary>
/// Writes a raw json token to the internal buffer.
/// </summary>
/// <param name="jsonTokenType">The JsonTokenType of the rawJsonToken</param>
/// <param name="rawJsonToken">The raw json token.</param>
protected override void WriteRawJsonToken(JsonTokenType jsonTokenType, IReadOnlyList<byte> rawJsonToken)
{
throw new NotImplementedException();
}
/// <summary>
/// Writes a character to the stream.
/// </summary>
/// <param name="value">The character to write to the stream.</param>
private void WriteChar(char value)
{
this.streamWriter.Write(value);
}
/// <summary>
/// Will insert a member separator token if one is needed.
/// </summary>
private void PrefixMemberSeparator()
{
if (!this.firstValue)
{
this.WriteChar(MemberSeperatorToken);
}
this.firstValue = false;
}
private bool RequiresEscapeSequence(char value)
{
switch (value)
{
case '\\':
case '"':
case '/':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
return true;
default:
return value < ' ';
}
}
private char GetHexDigit(byte value)
{
if (value > 0xF)
{
throw new ArgumentException("value must be less than 0xF");
}
return (value < 10) ? (char)('0' + value) : (char)('a' + value - 10);
}
private void WriteEscapedStringToStreamWriter(string value, StreamWriter streamWriter)
{
int readOffset = 0;
while (readOffset != value.Length)
{
if (!this.RequiresEscapeSequence(value[readOffset]))
{
// Just write the character as is
this.streamWriter.Write(value[readOffset++]);
}
else
{
char characterToEscape = value[readOffset++];
char escapeSequence = default(char);
switch (characterToEscape)
{
case '\\':
escapeSequence = '\\';
break;
case '"':
escapeSequence = '"';
break;
case '/':
escapeSequence = '/';
break;
case '\b':
escapeSequence = 'b';
break;
case '\f':
escapeSequence = 'f';
break;
case '\n':
escapeSequence = 'n';
break;
case '\r':
escapeSequence = 'r';
break;
case '\t':
escapeSequence = 't';
break;
}
if (escapeSequence >= ' ')
{
// We got a special character
streamWriter.Write('\\');
streamWriter.Write(escapeSequence);
}
else
{
// We got a control character (U+0000 through U+001F).
streamWriter.Write('\\');
streamWriter.Write('u');
streamWriter.Write(this.GetHexDigit((byte)(((byte)characterToEscape >> 12) & 0xF)));
streamWriter.Write(this.GetHexDigit((byte)(((byte)characterToEscape >> 8) & 0xF)));
streamWriter.Write(this.GetHexDigit((byte)(((byte)characterToEscape >> 4) & 0xF)));
streamWriter.Write(this.GetHexDigit((byte)(((byte)characterToEscape) & 0xF)));
}
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,373 @@
//-----------------------------------------------------------------------
// <copyright file="JsonWriter.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Azure.Documents;
/// <summary>
/// Base abstract class for JSON writers.
/// The writer defines methods that allow for writing a JSON encoded value to a buffer.
/// </summary>
internal abstract partial class JsonWriter : IJsonWriter
{
/// <summary>
/// The <see cref="JsonObjectState"/>
/// </summary>
protected readonly JsonObjectState JsonObjectState;
/// <summary>
/// Whether to skip validation.
/// </summary>
protected readonly bool SkipValidation;
/// <summary>
/// Initializes a new instance of the JsonWriter class.
/// </summary>
/// <param name="skipValidation">Whether or not to skip validation.</param>
protected JsonWriter(bool skipValidation)
{
this.JsonObjectState = new JsonObjectState(false);
this.SkipValidation = skipValidation;
}
/// <summary>
/// Gets the SerializationFormat of the JsonWriter.
/// </summary>
public abstract JsonSerializationFormat SerializationFormat { get; }
/// <summary>
/// Gets the current length of the internal buffer.
/// </summary>
public abstract long CurrentLength { get; }
/// <summary>
/// Creates a JsonTextWriter that can write in a particular encoding
/// </summary>
/// <param name="encoding">The encoding to write in.</param>
/// <param name="skipValidation">Whether or not to skip validation</param>
/// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
public static IJsonWriter Create(Encoding encoding, bool skipValidation = false)
{
if (encoding != Encoding.UTF8 && encoding != Encoding.Unicode && encoding != Encoding.UTF32)
{
throw new ArgumentException("Text encoding must be UTF8, UTF16 / Unicode or UTF32");
}
return new JsonTextWriter(encoding, skipValidation);
}
/// <summary>
/// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text)
/// </summary>
/// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param>
/// <param name="skipValidation">Whether or not to skip validation</param>
/// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
public static IJsonWriter Create(JsonSerializationFormat jsonSerializationFormat, bool skipValidation = false)
{
switch (jsonSerializationFormat)
{
case JsonSerializationFormat.Text:
return new JsonTextWriter(Encoding.UTF8, skipValidation);
case JsonSerializationFormat.Binary:
return new JsonBinaryWriter(skipValidation, false);
default:
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat));
}
}
/// <summary>
/// Writes the object start symbol to internal buffer.
/// </summary>
public abstract void WriteObjectStart();
/// <summary>
/// Writes the object end symbol to the internal buffer.
/// </summary>
public abstract void WriteObjectEnd();
/// <summary>
/// Writes the array start symbol to the internal buffer.
/// </summary>
public abstract void WriteArrayStart();
/// <summary>
/// Writes the array end symbol to the internal buffer.
/// </summary>
public abstract void WriteArrayEnd();
/// <summary>
/// Writes a field name to the the internal buffer.
/// </summary>
/// <param name="fieldName">The name of the field to write.</param>
public abstract void WriteFieldName(string fieldName);
/// <summary>
/// Writes a string to the internal buffer.
/// </summary>
/// <param name="value">The value of the string to write.</param>
public abstract void WriteStringValue(string value);
/// <summary>
/// Writes an integer to the internal buffer.
/// </summary>
/// <param name="value">The value of the integer to write.</param>
public abstract void WriteIntValue(long value);
/// <summary>
/// Writes a number to the internal buffer.
/// </summary>
/// <param name="value">The value of the number to write.</param>
public abstract void WriteNumberValue(double value);
/// <summary>
/// Writes a boolean to the internal buffer.
/// </summary>
/// <param name="value">The value of the boolean to write.</param>
public abstract void WriteBoolValue(bool value);
/// <summary>
/// Writes a null to the internal buffer.
/// </summary>
public abstract void WriteNullValue();
/// <summary>
/// Writes current token from a json reader to the internal buffer.
/// </summary>
/// <param name="jsonReader">The JsonReader to the get the current token from.</param>
public void WriteCurrentToken(IJsonReader jsonReader)
{
if (jsonReader == null)
{
throw new ArgumentNullException("jsonReader can not be null");
}
// For now short circuit this to false until we figure out how to optimize this.
bool sameFormat = jsonReader.SerializationFormat == this.SerializationFormat && false;
JsonTokenType jsonTokenType = jsonReader.CurrentTokenType;
switch (jsonTokenType)
{
case JsonTokenType.NotStarted:
break;
case JsonTokenType.BeginArray:
this.WriteArrayStart();
break;
case JsonTokenType.EndArray:
this.WriteArrayEnd();
break;
case JsonTokenType.BeginObject:
this.WriteObjectStart();
break;
case JsonTokenType.EndObject:
this.WriteObjectEnd();
break;
case JsonTokenType.True:
this.WriteBoolValue(true);
break;
case JsonTokenType.False:
this.WriteBoolValue(false);
break;
case JsonTokenType.Null:
this.WriteNullValue();
break;
case JsonTokenType.String:
case JsonTokenType.Number:
case JsonTokenType.FieldName:
{
if (sameFormat)
{
IReadOnlyList<byte> bufferedRawJson = jsonReader.GetBufferedRawJsonToken();
this.WriteRawJsonToken(jsonTokenType, bufferedRawJson);
}
else
{
if (jsonTokenType == JsonTokenType.Number)
{
double number = jsonReader.GetNumberValue();
this.WriteNumberValue(number);
}
else
{
string value = jsonReader.GetStringValue();
if (jsonTokenType == JsonTokenType.FieldName)
{
this.WriteFieldName(value);
}
else
{
this.WriteStringValue(value);
}
}
}
break;
}
default:
throw new ArgumentException($"Unexpected JsonTokenType: {jsonTokenType}");
}
}
/// <summary>
/// Writes every token from the JsonReader to the internal buffer.
/// </summary>
/// <param name="jsonReader">The JsonReader to get the tokens from.</param>
public void WriteAll(IJsonReader jsonReader)
{
if (jsonReader == null)
{
throw new ArgumentNullException("jsonReader can not be null");
}
while (jsonReader.Read())
{
this.WriteCurrentToken(jsonReader);
}
}
/// <summary>
/// Writes a fragment of a json to the internal buffer
/// </summary>
/// <param name="jsonFragment">A section of a valid json</param>
public void WriteJsonFragment(IReadOnlyList<byte> jsonFragment)
{
if (jsonFragment == null)
{
throw new ArgumentNullException("jsonFragment can not be null");
}
IJsonReader jsonReader = JsonReader.Create(new MemoryStream(jsonFragment.ToArray()));
this.WriteAll(jsonReader);
}
/// <summary>
/// Writes a json node to the internal buffer.
/// </summary>
/// <param name="jsonNavigator">The navigator to use to navigate the node</param>
/// <param name="jsonNavigatorNode">The node to write.</param>
public void WriteJsonNode(IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode)
{
if (jsonNavigator == null)
{
throw new ArgumentNullException($"{nameof(jsonNavigator)} can not be null");
}
if (jsonNavigatorNode == null)
{
throw new ArgumentNullException($"{nameof(jsonNavigatorNode)} can not be null");
}
// For now short circuit this to false until we figure out how to optimize this.
bool sameFormat = jsonNavigator.SerializationFormat == this.SerializationFormat && false;
JsonNodeType jsonNodeType = jsonNavigator.GetNodeType(jsonNavigatorNode);
// See if we can write the node without looking at it's value
switch (jsonNodeType)
{
case JsonNodeType.Null:
this.WriteNullValue();
return;
case JsonNodeType.False:
this.WriteBoolValue(false);
return;
case JsonNodeType.True:
this.WriteBoolValue(true);
return;
}
// If the navigator has the same format as this writer then we try to retrieve the node raw JSON
IReadOnlyList<byte> bufferedRawJson;
if (sameFormat && jsonNavigator.TryGetBufferedRawJson(jsonNavigatorNode, out bufferedRawJson))
{
// Token type really doesn't make any difference other than whether this is a field name
JsonTokenType jsonTokenType = (jsonNodeType == JsonNodeType.FieldName ? JsonTokenType.FieldName : JsonTokenType.Null);
this.WriteRawJsonToken(jsonTokenType, bufferedRawJson);
}
else
{
// Either the formats did not match or we couldn't retrieve the buffered raw JSON
switch (jsonNodeType)
{
case JsonNodeType.Number:
double numberValue = jsonNavigator.GetNumberValue(jsonNavigatorNode);
this.WriteNumberValue(numberValue);
break;
case JsonNodeType.String:
case JsonNodeType.FieldName:
bool fieldName = jsonNodeType == JsonNodeType.FieldName;
IReadOnlyList<byte> bufferedStringValue;
if (jsonNavigator.TryGetBufferedStringValue(jsonNavigatorNode, out bufferedStringValue))
{
if (fieldName)
{
this.WriteRawJsonToken(JsonTokenType.FieldName, bufferedStringValue);
}
else
{
this.WriteRawJsonToken(JsonTokenType.String, bufferedStringValue);
}
}
else
{
string value = jsonNavigator.GetStringValue(jsonNavigatorNode);
if (fieldName)
{
this.WriteFieldName(value);
}
else
{
this.WriteStringValue(value);
}
}
break;
case JsonNodeType.Array:
this.WriteArrayStart();
foreach (IJsonNavigatorNode arrayItem in jsonNavigator.GetArrayItems(jsonNavigatorNode))
{
this.WriteJsonNode(jsonNavigator, arrayItem);
}
this.WriteArrayEnd();
break;
case JsonNodeType.Object:
this.WriteObjectStart();
foreach (ObjectProperty objectProperty in jsonNavigator.GetObjectProperties(jsonNavigatorNode))
{
this.WriteJsonNode(jsonNavigator, objectProperty.NameNode);
this.WriteJsonNode(jsonNavigator, objectProperty.ValueNode);
}
this.WriteObjectEnd();
break;
default:
throw new ArgumentException($"Unexpected JsonNodeType: {jsonNodeType}");
}
}
}
/// <summary>
/// Gets the result of the JsonWriter.
/// </summary>
/// <returns>The result of the JsonWriter as an array of bytes.</returns>
public abstract byte[] GetResult();
/// <summary>
/// Writes a raw json token to the internal buffer.
/// </summary>
/// <param name="jsonTokenType">The JsonTokenType of the rawJsonToken</param>
/// <param name="rawJsonToken">The raw json token.</param>
protected abstract void WriteRawJsonToken(JsonTokenType jsonTokenType, IReadOnlyList<byte> rawJsonToken);
}
}

Просмотреть файл

@ -0,0 +1,186 @@
//-----------------------------------------------------------------------
// <copyright file="LittleEndianBinaryReader.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
using System.IO;
using System.Text;
/// <summary>
/// A BinaryReader that can read binary that has little endian byte ordering for a client that can be run a both a big endian and little endian machine.
/// </summary>
internal sealed class LittleEndianBinaryReader : BinaryReader
{
/// <summary>
/// Flag used to determine if the machine is a little endian machine.
/// </summary>
private readonly bool isLittleEndian;
/// <summary>
/// Initializes a new instance of the LittleEndianBinaryReader class based on the specified stream and using UTF-8 encoding.
/// </summary>
/// <param name="input">The input stream.</param>
public LittleEndianBinaryReader(Stream input)
: this(input, Encoding.UTF8)
{
}
/// <summary>
/// Initializes a new instance of the LittleEndianBinaryReader class based on the specified stream and character encoding.
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="encoding">The character encoding to use.</param>
public LittleEndianBinaryReader(Stream input, Encoding encoding)
: this(input, encoding, false)
{
}
/// <summary>
/// Initializes a new instance of the LittleEndianBinaryReader class based on the specified stream and character encoding, and optionally leaves the stream open.
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="encoding">The character encoding to use.</param>
/// <param name="leaveOpen">true to leave the stream open after the System.IO.BinaryReader object is disposed; otherwise, false.</param>
public LittleEndianBinaryReader(Stream input, Encoding encoding, bool leaveOpen)
: this(input, encoding, leaveOpen, BitConverter.IsLittleEndian)
{
}
/// <summary>
/// Initializes a new instance of the LittleEndianBinaryReader class for testing purposes, since we don't want the user to be able to tell us what the endianness of the machine is.
/// Thus this constructor is private.
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="encoding">The character encoding to use.</param>
/// <param name="leaveOpen">true to leave the stream open after the System.IO.BinaryReader object is disposed; otherwise, false.</param>
/// <param name="isLittleEndian">Whether the machine is a little endian machine</param>
private LittleEndianBinaryReader(Stream input, Encoding encoding, bool leaveOpen, bool isLittleEndian)
: base(input, encoding, leaveOpen)
{
this.isLittleEndian = isLittleEndian;
}
/// <summary>
/// Reads a Boolean value from the current stream and advances the current position of the stream by one byte.
/// </summary>
/// <returns>true if the byte is nonzero; otherwise, false.</returns>
public override bool ReadBoolean()
{
// Bools are just 1 byte so we can just return what the base class does.
return base.ReadBoolean();
}
/// <summary>
/// Reads the next byte from the current stream and advances the current position of the stream by one byte.
/// </summary>
/// <returns>The next byte read from the current stream.</returns>
public override byte ReadByte()
{
// A single byte has no byte order so we can just pass it down to the base class
return base.ReadByte();
}
/// <summary>
/// Reads the next decimal from the current stream and advances the current position of the stream by 16 bytes.
/// </summary>
/// <returns>The next decimal read from the current stream.</returns>
public override decimal ReadDecimal()
{
throw new NotSupportedException();
}
/// <summary>
/// Reads an 8-byte floating point value from the current stream and advances the current position of the stream by eight bytes.
/// </summary>
/// <returns>An 8-byte floating point value read from the current stream.</returns>
public override double ReadDouble()
{
return this.isLittleEndian ? base.ReadDouble() : ByteOrder.Reverse(base.ReadDouble());
}
/// <summary>
/// Reads a 2-byte signed integer from the current stream and advances the current position of the stream by two bytes.
/// </summary>
/// <returns> A 2-byte signed integer read from the current stream.</returns>
public override short ReadInt16()
{
return this.isLittleEndian ? base.ReadInt16() : ByteOrder.Reverse(base.ReadInt16());
}
/// <summary>
/// Reads a 4-byte signed integer from the current stream and advances the current position of the stream by four bytes.
/// </summary>
/// <returns>A 4-byte signed integer read from the current stream.</returns>
public override int ReadInt32()
{
return this.isLittleEndian ? base.ReadInt32() : ByteOrder.Reverse(base.ReadInt32());
}
/// <summary>
/// Reads an 8-byte signed integer from the current stream and advances the current position of the stream by eight bytes.
/// </summary>
/// <returns>An 8-byte signed integer read from the current stream.</returns>
public override long ReadInt64()
{
return this.isLittleEndian ? base.ReadInt64() : ByteOrder.Reverse(base.ReadInt64());
}
/// <summary>
/// Reads a signed byte from this stream and advances the current position of the stream by one byte.
/// </summary>
/// <returns>A signed byte read from the current stream.</returns>
public override sbyte ReadSByte()
{
// A single byte has no byte order.
return base.ReadSByte();
}
/// <summary>
/// Reads a 4-byte floating point value from the current stream and advances the current position of the stream by four bytes.
/// </summary>
/// <returns>A 4-byte floating point value read from the current stream.</returns>
public override float ReadSingle()
{
return this.isLittleEndian ? base.ReadSingle() : ByteOrder.Reverse(base.ReadSingle());
}
/// <summary>
/// Reads a string from the current stream. The string is prefixed with the length, encoded as an integer seven bits at a time.
/// </summary>
/// <returns>The string being read.</returns>
public override string ReadString()
{
throw new NotSupportedException();
}
/// <summary>
/// Reads a 2-byte unsigned integer from the current stream and advances the position of the stream by two bytes.
/// </summary>
/// <returns>A 2-byte unsigned integer from the current stream</returns>
public override ushort ReadUInt16()
{
return this.isLittleEndian ? base.ReadUInt16() : ByteOrder.Reverse(base.ReadUInt16());
}
/// <summary>
/// Reads a 4-byte unsigned integer from the current stream and advances the position of the stream by four bytes.
/// </summary>
/// <returns>A 4-byte unsigned integer read from this stream.</returns>
public override uint ReadUInt32()
{
return this.isLittleEndian ? base.ReadUInt32() : ByteOrder.Reverse(base.ReadUInt32());
}
/// <summary>
/// Reads an 8-byte unsigned integer from the current stream and advances the position of the stream by eight bytes.
/// </summary>
/// <returns>An 8-byte unsigned integer read from this stream.</returns>
public override ulong ReadUInt64()
{
return this.isLittleEndian ? base.ReadUInt64() : ByteOrder.Reverse(base.ReadUInt64());
}
}
}

Просмотреть файл

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------
// <copyright file="ObjectProperty.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Json
{
using System;
/// <summary>
/// Struct to hold the property name and property value for an object property.
/// </summary>
internal struct ObjectProperty
{
/// <summary>
/// The IJsonNavigatorNode to the node that holds the object property name.
/// </summary>
public readonly IJsonNavigatorNode NameNode;
/// <summary>
/// The IJsonNavigatorNode to the node that holds the object property value.
/// </summary>
public readonly IJsonNavigatorNode ValueNode;
/// <summary>
/// Initializes a new instance of the ObjectProperty struct.
/// </summary>
/// <param name="nameNode">The IJsonNavigatorNode to the node that holds the object property name.</param>
/// <param name="valueNode">The IJsonNavigatorNode to the node that holds the object property value.</param>
public ObjectProperty(IJsonNavigatorNode nameNode, IJsonNavigatorNode valueNode)
{
if (nameNode == null)
{
throw new ArgumentNullException("nameNode");
}
if (valueNode == null)
{
throw new ArgumentNullException("valueNode");
}
this.NameNode = nameNode;
this.ValueNode = valueNode;
}
}
}

Просмотреть файл

@ -15,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Reflection;
using Microsoft.Azure.Cosmos;
using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings;
using Microsoft.Azure.Documents;
internal abstract class BuiltinFunctionVisitor
{

Просмотреть файл

@ -15,12 +15,15 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents.Routing;
/// <summary>
/// Provides interface for historical change feed.
/// </summary>
/// <typeparam name="TResource">Source Resource Type (e.g. Document)</typeparam>
internal sealed class ChangeFeedQuery<TResource> : IDocumentQuery<TResource> where TResource : CosmosResource, new()
internal sealed class ChangeFeedQuery<TResource> : IDocumentQuery<TResource> where TResource : new()
{
#region Fields
private const string IfNoneMatchAllHeaderValue = "*"; // This means start from current.

Просмотреть файл

@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using Microsoft.Azure.Cosmos.Linq;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal partial class DocumentClient
{
@ -25,11 +26,11 @@ namespace Microsoft.Azure.Cosmos
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosDatabaseSettings"/>
/// <seealso cref="Database"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IOrderedQueryable<CosmosDatabaseSettings> CreateDatabaseQuery(FeedOptions feedOptions = null)
public IOrderedQueryable<Database> CreateDatabaseQuery(FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosDatabaseSettings>(this, ResourceType.Database, typeof(CosmosDatabaseSettings), Paths.Databases_Root, feedOptions);
return new DocumentQuery<Database>(this, ResourceType.Database, typeof(Database), Paths.Databases_Root, feedOptions);
}
/// <summary>
@ -47,7 +48,7 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosDatabaseSettings"/>
/// <seealso cref="Database"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateDatabaseQuery(string sqlExpression, FeedOptions feedOptions = null)
{
@ -72,11 +73,11 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosDatabaseSettings"/>
/// <seealso cref="Database"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateDatabaseQuery(SqlQuerySpec querySpec, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosDatabaseSettings>(this, ResourceType.Database, typeof(CosmosDatabaseSettings), Paths.Databases_Root, feedOptions).AsSQL(querySpec);
return new DocumentQuery<Database>(this, ResourceType.Database, typeof(Database), Paths.Databases_Root, feedOptions).AsSQL(querySpec);
}
/// <summary>
@ -85,10 +86,11 @@ namespace Microsoft.Azure.Cosmos
/// </summary>
/// <param name="feedOptions">The options for processing the query results feed.</param>
/// <returns>the query result set.</returns>
internal IDocumentQuery<CosmosDatabaseSettings> CreateDatabaseChangeFeedQuery(ChangeFeedOptions feedOptions)
internal IDocumentQuery<Database> CreateDatabaseChangeFeedQuery(ChangeFeedOptions feedOptions)
{
ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
return new ChangeFeedQuery<CosmosDatabaseSettings>(this, ResourceType.Database, null, feedOptions);
throw new NotImplementedException();
////ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
////return new Document.ChangeFeedQuery<Database>(this, ResourceType.Database, null, feedOptions);
}
/// <summary>
@ -105,11 +107,11 @@ namespace Microsoft.Azure.Cosmos
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="DocumentCollection"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IOrderedQueryable<CosmosContainerSettings> CreateDocumentCollectionQuery(string databaseLink, FeedOptions feedOptions = null)
public IOrderedQueryable<DocumentCollection> CreateDocumentCollectionQuery(string databaseLink, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosContainerSettings>(this, ResourceType.Collection, typeof(CosmosContainerSettings), databaseLink, feedOptions);
return new DocumentQuery<DocumentCollection>(this, ResourceType.Collection, typeof(DocumentCollection), databaseLink, feedOptions);
}
/// <summary>
@ -128,7 +130,7 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="DocumentCollection"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateDocumentCollectionQuery(string databaseLink, string sqlExpression, FeedOptions feedOptions = null)
{
@ -153,11 +155,11 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosContainerSettings"/>
/// <seealso cref="DocumentCollection"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateDocumentCollectionQuery(string databaseLink, SqlQuerySpec querySpec, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosContainerSettings>(this, ResourceType.Collection, typeof(CosmosContainerSettings), databaseLink, feedOptions).AsSQL(querySpec);
return new DocumentQuery<DocumentCollection>(this, ResourceType.Collection, typeof(DocumentCollection), databaseLink, feedOptions).AsSQL(querySpec);
}
/// <summary>
@ -167,15 +169,16 @@ namespace Microsoft.Azure.Cosmos
/// <param name="databaseLink">Specifies the database to read collections from.</param>
/// <param name="feedOptions">Specifies the options for processing the query results feed.</param>
/// <returns>the query result set.</returns>
internal IDocumentQuery<CosmosContainerSettings> CreateDocumentCollectionChangeFeedQuery(string databaseLink, ChangeFeedOptions feedOptions)
internal IDocumentQuery<DocumentCollection> CreateDocumentCollectionChangeFeedQuery(string databaseLink, ChangeFeedOptions feedOptions)
{
if(string.IsNullOrEmpty(databaseLink))
{
throw new ArgumentException(nameof(databaseLink));
}
throw new NotImplementedException();
////if(string.IsNullOrEmpty(databaseLink))
////{
//// throw new ArgumentException(nameof(databaseLink));
////}
ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
return new ChangeFeedQuery<CosmosContainerSettings>(this, ResourceType.Collection, databaseLink, feedOptions);
////ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
////return new ChangeFeedQuery<DocumentCollection>(this, ResourceType.Collection, databaseLink, feedOptions);
}
/// <summary>
@ -192,11 +195,11 @@ namespace Microsoft.Azure.Cosmos
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosStoredProcedureSettings"/>
/// <seealso cref="StoredProcedure"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IOrderedQueryable<CosmosStoredProcedureSettings> CreateStoredProcedureQuery(string collectionLink, FeedOptions feedOptions = null)
public IOrderedQueryable<StoredProcedure> CreateStoredProcedureQuery(string collectionLink, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosStoredProcedureSettings>(this, ResourceType.StoredProcedure, typeof(CosmosStoredProcedureSettings), collectionLink, feedOptions);
return new DocumentQuery<StoredProcedure>(this, ResourceType.StoredProcedure, typeof(StoredProcedure), collectionLink, feedOptions);
}
/// <summary>
@ -215,7 +218,7 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosStoredProcedureSettings"/>
/// <seealso cref="StoredProcedure"/>
public IQueryable<dynamic> CreateStoredProcedureQuery(string collectionLink, string sqlExpression, FeedOptions feedOptions = null)
{
return this.CreateStoredProcedureQuery(collectionLink, new SqlQuerySpec(sqlExpression), feedOptions);
@ -239,10 +242,10 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosStoredProcedureSettings"/>
/// <seealso cref="StoredProcedure"/>
public IQueryable<dynamic> CreateStoredProcedureQuery(string collectionLink, SqlQuerySpec querySpec, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosStoredProcedureSettings>(this, ResourceType.StoredProcedure, typeof(CosmosStoredProcedureSettings), collectionLink, feedOptions).AsSQL(querySpec);
return new DocumentQuery<StoredProcedure>(this, ResourceType.StoredProcedure, typeof(StoredProcedure), collectionLink, feedOptions).AsSQL(querySpec);
}
/// <summary>
@ -259,11 +262,11 @@ namespace Microsoft.Azure.Cosmos
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosTriggerSettings"/>
/// <seealso cref="Trigger"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IOrderedQueryable<CosmosTriggerSettings> CreateTriggerQuery(string collectionLink, FeedOptions feedOptions = null)
public IOrderedQueryable<Trigger> CreateTriggerQuery(string collectionLink, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosTriggerSettings>(this, ResourceType.Trigger, typeof(CosmosTriggerSettings), collectionLink, feedOptions);
return new DocumentQuery<Trigger>(this, ResourceType.Trigger, typeof(Trigger), collectionLink, feedOptions);
}
/// <summary>
@ -282,7 +285,7 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosTriggerSettings"/>
/// <seealso cref="Trigger"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateTriggerQuery(string collectionLink, string sqlExpression, FeedOptions feedOptions = null)
{
@ -307,11 +310,11 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosTriggerSettings"/>
/// <seealso cref="Trigger"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateTriggerQuery(string collectionLink, SqlQuerySpec querySpec, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosTriggerSettings>(this, ResourceType.Trigger, typeof(CosmosTriggerSettings), collectionLink, feedOptions).AsSQL(querySpec);
return new DocumentQuery<Trigger>(this, ResourceType.Trigger, typeof(Trigger), collectionLink, feedOptions).AsSQL(querySpec);
}
/// <summary>
@ -328,11 +331,11 @@ namespace Microsoft.Azure.Cosmos
/// ]]>
/// </code>
/// </example>
/// <seealso cref="CosmosUserDefinedFunctionSettings"/>
/// <seealso cref="UserDefinedFunction"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IOrderedQueryable<CosmosUserDefinedFunctionSettings> CreateUserDefinedFunctionQuery(string collectionLink, FeedOptions feedOptions = null)
public IOrderedQueryable<UserDefinedFunction> CreateUserDefinedFunctionQuery(string collectionLink, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosUserDefinedFunctionSettings>(this, ResourceType.UserDefinedFunction, typeof(CosmosUserDefinedFunctionSettings), collectionLink, feedOptions);
return new DocumentQuery<UserDefinedFunction>(this, ResourceType.UserDefinedFunction, typeof(UserDefinedFunction), collectionLink, feedOptions);
}
/// <summary>
@ -351,7 +354,7 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosUserDefinedFunctionSettings"/>
/// <seealso cref="UserDefinedFunction"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateUserDefinedFunctionQuery(string collectionLink, string sqlExpression, FeedOptions feedOptions = null)
{
@ -376,11 +379,11 @@ namespace Microsoft.Azure.Cosmos
/// </code>
/// </example>
/// <remarks>Refer to https://msdn.microsoft.com/en-us/library/azure/dn782250.aspx and http://azure.microsoft.com/documentation/articles/documentdb-sql-query/ for syntax and examples.</remarks>
/// <seealso cref="CosmosUserDefinedFunctionSettings"/>
/// <seealso cref="UserDefinedFunction"/>
/// <seealso cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery"/>
public IQueryable<dynamic> CreateUserDefinedFunctionQuery(string collectionLink, SqlQuerySpec querySpec, FeedOptions feedOptions = null)
{
return new DocumentQuery<CosmosUserDefinedFunctionSettings>(this, ResourceType.UserDefinedFunction, typeof(CosmosUserDefinedFunctionSettings), collectionLink, feedOptions).AsSQL(querySpec);
return new DocumentQuery<UserDefinedFunction>(this, ResourceType.UserDefinedFunction, typeof(UserDefinedFunction), collectionLink, feedOptions).AsSQL(querySpec);
}
/// <summary>
@ -1091,13 +1094,14 @@ namespace Microsoft.Azure.Cosmos
/// <returns>the query result set.</returns>
internal IDocumentQuery<UserDefinedType> CreateUserDefinedTypeChangeFeedQuery(string databaseLink, ChangeFeedOptions feedOptions)
{
if (string.IsNullOrEmpty(databaseLink))
{
throw new ArgumentException(nameof(databaseLink));
}
throw new NotImplementedException();
////if (string.IsNullOrEmpty(databaseLink))
////{
//// throw new ArgumentException(nameof(databaseLink));
////}
ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
return new ChangeFeedQuery<UserDefinedType>(this, ResourceType.UserDefinedType, databaseLink, feedOptions);
////ValidateChangeFeedOptionsForNotPartitionedResource(feedOptions);
////return new ChangeFeedQuery<UserDefinedType>(this, ResourceType.UserDefinedType, databaseLink, feedOptions);
}
#endregion Query Methods

Просмотреть файл

@ -16,6 +16,8 @@ namespace Microsoft.Azure.Cosmos.Linq
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Просмотреть файл

@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.Azure.Documents;
internal static class DocumentQueryEvaluator
{

Просмотреть файл

@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System;
using System.Runtime.Serialization;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Represents an exception from the Azure Cosmos DB service queries.

Просмотреть файл

@ -11,6 +11,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Documents;
internal interface IDocumentQueryProvider : IQueryProvider
{

Просмотреть файл

@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Documents;
/// <summary>
/// This class provides extension methods for converting a <see cref="System.Linq.IQueryable{T}"/> object to a <see cref="Microsoft.Azure.Cosmos.Linq.IDocumentQuery{T}"/> object.

Двоичный файл не отображается.

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
internal static class TypeSystem

Просмотреть файл

@ -4,6 +4,7 @@
namespace Microsoft.Azure.Cosmos
{
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Documents.Collections;
using System.Collections.Specialized;
using System.IO;

Просмотреть файл

@ -7,7 +7,7 @@
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<NeutralLanguage>en-US</NeutralLanguage>
<ClientVersion>3.0.0.9-preview</ClientVersion>
<DirectVersion>3.0.0.9-preview</DirectVersion>
<DirectVersion>3.0.0.20-preview</DirectVersion>
<Version Condition=" '$(IsNightly)' == '1' ">$(ClientVersion)-nightly$(CurrentDate)</Version>
<Version Condition=" '$(IsNightly)' == '0' Or '$(IsNightly)' == '' ">$(ClientVersion)</Version>
<FileVersion>$(VersionPrefix)</FileVersion>
@ -26,7 +26,7 @@
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<PlatformTarget>AnyCPU</PlatformTarget>
<ShippingScope>External</ShippingScope>
<SigningType>Product</SigningType>
@ -40,7 +40,7 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
<ItemGroup Condition=" '$(SignAssembly)' == 'true' ">
<PackageReference Include="Microsoft.Azure.Cosmos.Direct" Version="$(DirectVersion)" />
</ItemGroup>
@ -48,38 +48,18 @@
<ItemGroup Condition=" '$(SignAssembly)' != 'true' ">
<PackageReference Include="Microsoft.Azure.Cosmos.Direct.MyGet" Version="$(DirectVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<ItemGroup>
<Compile Remove="RuntimePerfCounters.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
<ItemGroup>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
<PackageReference Include="System.ServiceModel.Primitives" Version="4.5.0" />
</ItemGroup>
<PropertyGroup>
<DefineConstants>DOCDBCLIENT</DefineConstants>
<DefineConstants>$(DefineConstants);DOCDBCLIENT;NETSTANDARD20</DefineConstants>
<DefineConstants Condition=" '$(SignAssembly)' == 'true' ">$(DefineConstants);SignAssembly</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
<DefineConstants>$(DefineConstants);NETFX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);NETSTANDARD20</DefineConstants>
</PropertyGroup>
</Project>

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Common;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal class NullRequestSigner : IRequestSigner
{

Просмотреть файл

@ -1,72 +0,0 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Azure.Cosmos.Internal;
internal sealed class OfferFeedResource : CosmosResource, IEnumerable<Offer>
{
private static string CollectionName
{
get
{
return typeof(Offer).Name + "s";
}
}
public OfferFeedResource()
{
}
public int Count
{
get
{
return this.InnerCollection.Count;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.InnerCollection.GetEnumerator();
}
IEnumerator<Offer> IEnumerable<Offer>.GetEnumerator()
{
return this.InnerCollection.GetEnumerator();
}
internal Collection<Offer> InnerCollection
{
get
{
Collection<Offer> collection = base.GetObjectCollection<Offer>(
OfferFeedResource.CollectionName,
typeof(Offer),
this.AltLink,
OfferTypeResolver.ResponseOfferTypeResolver);
if (collection == null)
{
collection = new Collection<Offer>();
base.SetObjectCollection(OfferFeedResource.CollectionName, collection);
}
return collection;
}
set
{
base.SetObjectCollection(OfferFeedResource.CollectionName, value);
}
}
internal override void OnSave()
{
base.SetValue(Constants.Properties.Count, this.InnerCollection.Count);
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Common;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
internal sealed class PartitionKeyMismatchRetryPolicy : IDocumentClientRetryPolicy
{

Просмотреть файл

@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query
{
using System;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Documents;
internal struct AggregateItem
{

Просмотреть файл

@ -8,7 +8,8 @@ namespace Microsoft.Azure.Cosmos.Query.Aggregation
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Cosmos.CosmosElements;
/// <summary>

Просмотреть файл

@ -5,8 +5,8 @@
//-----------------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Query.Aggregation
{
using Microsoft.Azure.Cosmos.CosmosElements;
using System;
using Microsoft.Azure.Cosmos.CosmosElements;
/// <summary>
/// Concrete implementation of IAggregator that can take the global min/max from the local min/max of multiple partitions and continuations.

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Query.Aggregation
using System.Globalization;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Concrete implementation of IAggregator that can take the global sum from the local sum of multiple partitions and continuations.

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Collections.Generic
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
/// <summary>
/// Provides awaitable and bounding capabilities for thread-safe collections that implement IProducerConsumerCollection&lt;T&gt;.

Просмотреть файл

@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query
{
using System;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents.Routing;
using Newtonsoft.Json;
/// <summary>

Просмотреть файл

@ -20,6 +20,9 @@ namespace Microsoft.Azure.Cosmos.Query
using Microsoft.Azure.Cosmos.Collections;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents.Routing;
using Newtonsoft.Json;
using ParallelQuery;
using Routing;

Просмотреть файл

@ -17,6 +17,9 @@ namespace Microsoft.Azure.Cosmos.Query
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents.Routing;
using Newtonsoft.Json;
/// <summary>

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Query
using System.Text;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Newtonsoft.Json.Linq;
/// <summary>

Просмотреть файл

@ -10,6 +10,8 @@ namespace Microsoft.Azure.Cosmos.Query
using System.Text;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Routing;
using Newtonsoft.Json.Linq;
using Routing;

Просмотреть файл

@ -16,6 +16,7 @@ namespace Microsoft.Azure.Cosmos.Query
using Collections.Generic;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Routing;
/// <summary>

Просмотреть файл

@ -5,13 +5,12 @@
namespace Microsoft.Azure.Cosmos.Query
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Common;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Routing;
using System.Linq;
using Microsoft.Azure.Documents;
internal sealed class DocumentQueryClient : IDocumentQueryClient
{
@ -121,7 +120,7 @@ namespace Microsoft.Azure.Cosmos.Query
public async Task<ConsistencyLevel> GetDefaultConsistencyLevelAsync()
{
return await this.innerClient.GetDefaultConsistencyLevelAsync();
return (ConsistencyLevel)await this.innerClient.GetDefaultConsistencyLevelAsync();
}
public async Task<ConsistencyLevel?> GetDesiredConsistencyLevelAsync()

Просмотреть файл

@ -23,6 +23,9 @@ namespace Microsoft.Azure.Cosmos.Query
using Microsoft.Azure.Cosmos.Linq;
using Microsoft.Azure.Cosmos.Routing;
using Newtonsoft.Json;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents.Routing;
internal abstract class DocumentQueryExecutionContextBase : IDocumentQueryExecutionContext
{
@ -187,11 +190,11 @@ namespace Microsoft.Azure.Cosmos.Query
{
INameValueCollection requestHeaders = new StringKeyValueCollection();
ConsistencyLevel defaultConsistencyLevel = await this.client.GetDefaultConsistencyLevelAsync();
ConsistencyLevel? desiredConsistencyLevel = await this.client.GetDesiredConsistencyLevelAsync();
Cosmos.ConsistencyLevel defaultConsistencyLevel = (Cosmos.ConsistencyLevel)(await this.client.GetDefaultConsistencyLevelAsync());
Cosmos.ConsistencyLevel? desiredConsistencyLevel = (Cosmos.ConsistencyLevel?)await this.client.GetDesiredConsistencyLevelAsync();
if (!string.IsNullOrEmpty(feedOptions.SessionToken) && !ReplicatedResourceClient.IsReadingFromMaster(this.resourceTypeEnum, OperationType.ReadFeed))
{
if (defaultConsistencyLevel == ConsistencyLevel.Session || (desiredConsistencyLevel.HasValue && desiredConsistencyLevel.Value == ConsistencyLevel.Session))
if (defaultConsistencyLevel == Cosmos.ConsistencyLevel.Session || (desiredConsistencyLevel.HasValue && desiredConsistencyLevel.Value == Cosmos.ConsistencyLevel.Session))
{
// Query across partitions is not supported today. Master resources (for e.g., database)
// can span across partitions, whereas server resources (viz: collection, document and attachment)
@ -249,7 +252,7 @@ namespace Microsoft.Azure.Cosmos.Query
if (this.feedOptions.ConsistencyLevel.HasValue)
{
await this.client.EnsureValidOverwrite(feedOptions.ConsistencyLevel.Value);
await this.client.EnsureValidOverwrite((Documents.ConsistencyLevel)feedOptions.ConsistencyLevel.Value);
requestHeaders.Set(HttpConstants.HttpHeaders.ConsistencyLevel, this.feedOptions.ConsistencyLevel.Value.ToString());
}
else if (desiredConsistencyLevel.HasValue)
@ -553,8 +556,8 @@ namespace Microsoft.Azure.Cosmos.Query
private DocumentServiceRequest CreateReadFeedDocumentServiceRequest(INameValueCollection requestHeaders)
{
if (this.resourceTypeEnum == Microsoft.Azure.Cosmos.Internal.ResourceType.Database
|| this.resourceTypeEnum == Microsoft.Azure.Cosmos.Internal.ResourceType.Offer)
if (this.resourceTypeEnum == Documents.ResourceType.Database
|| this.resourceTypeEnum == Documents.ResourceType.Offer)
{
return DocumentServiceRequest.Create(
OperationType.ReadFeed,
@ -670,7 +673,7 @@ namespace Microsoft.Azure.Cosmos.Query
{
switch (resourceType)
{
case Internal.ResourceType.Collection:
case Documents.ResourceType.Collection:
return "DocumentCollections";
default:
return resourceType.ToResourceTypeString() + "s";

Просмотреть файл

@ -17,6 +17,8 @@ namespace Microsoft.Azure.Cosmos.Query
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query.ParallelQuery;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Routing;
/// <summary>
/// Factory class for creating the appropriate DocumentQueryExecutionContext for the provided type of query.

Просмотреть файл

@ -17,6 +17,8 @@ namespace Microsoft.Azure.Cosmos.Query.ExecutionComponent
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Cosmos.Query.Aggregation;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
/// <summary>
/// Execution component that is able to aggregate local aggregates from multiple continuations and partitions.

Просмотреть файл

@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.Query.ExecutionComponent
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Query.ExecutionComponent
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
internal sealed class SkipDocumentQueryExecutionComponent : DocumentQueryExecutionComponentBase

Просмотреть файл

@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Query.ExecutionComponent
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Internal;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
internal sealed class TakeDocumentQueryExecutionComponent : DocumentQueryExecutionComponentBase

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше