From d5e954cdbec2e3ddc9b4df7982a5965d3d2a7c54 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:01:06 -0800 Subject: [PATCH] [Hotfix] JSON Binary Encoding: Adds support for encoding uniform arrays (#4889) # Pull Request Template ## Description - JSON Binary Encoding: Adds support for encoding uniform arrays. ## Type of change Please delete options that are not relevant. - [x] New feature (non-breaking change which adds functionality) ## Closing issues To automatically close an issue: closes #IssueNumber --------- Co-authored-by: Samer Boshra --- Directory.Build.props | 4 +- .../contracts/API_3.45.2.txt | 1655 +++++ .../contracts/API_3.46.0-preview.2.txt | 1752 +++++ .../src/Json/IJsonBinaryWriterExtensions.cs | 4 +- .../src/Json/IJsonWriter.cs | 53 +- .../src/Json/JsonBinaryEncoding.Enumerator.cs | 136 +- .../src/Json/JsonBinaryEncoding.NodeTypes.cs | 16 +- .../src/Json/JsonBinaryEncoding.Numbers.cs | 178 +- .../src/Json/JsonBinaryEncoding.TypeMarker.cs | 84 +- .../Json/JsonBinaryEncoding.UniformArrays.cs | 193 + .../Json/JsonBinaryEncoding.ValueLengths.cs | 47 +- .../src/Json/JsonBinaryEncoding.cs | 23 +- .../Json/JsonNavigator.JsonBinaryNavigator.cs | 463 +- .../src/Json/JsonReader.JsonBinaryReader.cs | 288 +- .../src/Json/JsonTokenType.cs | 7 +- .../src/Json/JsonWriteOptions.cs | 34 + .../src/Json/JsonWriter.JsonBinaryWriter.cs | 1083 ++- Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs | 114 +- ...soft.Azure.Cosmos.Performance.Tests.csproj | 1 + .../Json/JsonNavigatorTests.cs | 303 +- .../Json/JsonReaderTests.cs | 236 +- .../Json/JsonRoundtripTests.cs | 527 +- .../Json/JsonTestUtils.cs | 870 ++- .../Json/JsonTokenInfo.cs | 73 +- .../Json/JsonWriterTests.cs | 6593 +++++++++++++++-- changelog.md | 8 + 26 files changed, 12967 insertions(+), 1778 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.45.2.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.46.0-preview.2.txt create mode 100644 Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.UniformArrays.cs create mode 100644 Microsoft.Azure.Cosmos/src/Json/JsonWriteOptions.cs diff --git a/Directory.Build.props b/Directory.Build.props index e19d8e8d50..3a5263e6a2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.45.1 + 3.45.2 3.46.0 - preview.1 + preview.2 3.37.1 2.0.4 2.1.0 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.45.2.txt b/Microsoft.Azure.Cosmos/contracts/API_3.45.2.txt new file mode 100644 index 0000000000..3041fe3739 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.45.2.txt @@ -0,0 +1,1655 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract FeedRange FeedRange { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public virtual Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + public VectorEmbeddingPolicy VectorEmbeddingPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public IEnumerable AccountInitializationCustomEndpoints { get; set; } + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public JsonSerializerOptions UseSystemTextJsonSerializerWithOptions { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + public QueryTextMode QueryTextMode { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public abstract class CosmosLinqSerializer : CosmosSerializer + { + protected CosmosLinqSerializer(); + public abstract string SerializeMemberName(MemberInfo memberInfo); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public Nullable PayloadSizeThresholdInBytes { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + public Nullable RequestChargeThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public enum DistanceFunction + { + Cosine = 1, + DotProduct = 2, + Euclidean = 0, + } + public class Embedding : IEquatable + { + public Embedding(); + public VectorDataType DataType { get; set; } + public int Dimensions { get; set; } + public DistanceFunction DistanceFunction { get; set; } + public string Path { get; set; } + public bool Equals(Embedding that); + public void ValidateEmbeddingPath(); + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + public Collection VectorIndexes { get; set; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public QueryTextMode QueryTextMode { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public enum QueryTextMode + { + All = 2, + None = 0, + ParameterizedOnly = 1, + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string AustriaEast = "Austria East"; + public const string BleuFranceCentral = "Bleu France Central"; + public const string BleuFranceSouth = "Bleu France South"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChileCentral = "Chile Central"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string DelosCloudGermanyCentral = "Delos Cloud Germany Central"; + public const string DelosCloudGermanyNorth = "Delos Cloud Germany North"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyNorth = "Germany North"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IndonesiaCentral = "Indonesia Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MalaysiaWest = "Malaysia West"; + public const string MexicoCentral = "Mexico Central"; + public const string NewZealandNorth = "New Zealand North"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SouthCentralUS2 = "South Central US 2"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SoutheastUS = "Southeast US"; + public const string SouthIndia = "South India"; + public const string SouthwestUS = "Southwest US"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string TaiwanNorth = "Taiwan North"; + public const string TaiwanNorthwest = "Taiwan Northwest"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string USSecWestCentral = "USSec West Central"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } + public enum VectorDataType + { + Float32 = 0, + Int8 = 2, + Uint8 = 1, + } + public sealed class VectorEmbeddingPolicy + { + public readonly Collection Embeddings; + public VectorEmbeddingPolicy(Collection embeddings); + } + public sealed class VectorIndexPath + { + public VectorIndexPath(); + public string Path { get; set; } + public VectorIndexType Type { get; set; } + } + public enum VectorIndexType + { + DiskANN = 1, + Flat = 0, + QuantizedFlat = 2, + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + public VectorEmbeddingPolicyDefinition WithVectorEmbeddingPolicy(Collection embeddings); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomAccountEndpoints(IEnumerable customAccountEndpoints); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithSystemTextJsonSerializerOptions(JsonSerializerOptions serializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + public VectorIndexDefinition> WithVectorIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } + public class VectorEmbeddingPolicyDefinition + { + public VectorEmbeddingPolicyDefinition(ContainerBuilder parent, Collection embeddings, Action attachCallback); + public ContainerBuilder Attach(); + } + public class VectorIndexDefinition + { + public VectorIndexDefinition(T parent, Action attachCallback); + public T Attach(); + public VectorIndexDefinition Path(string path, VectorIndexType indexType); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static int DocumentId(this object obj); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.46.0-preview.2.txt b/Microsoft.Azure.Cosmos/contracts/API_3.46.0-preview.2.txt new file mode 100644 index 0000000000..da2d3b0fb6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.46.0-preview.2.txt @@ -0,0 +1,1752 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public abstract class AvailabilityStrategy + { + public static AvailabilityStrategy CrossRegionHedgingStrategy(TimeSpan threshold, Nullable thresholdStep); + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItem + { + public ChangeFeedItem(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract FeedRange FeedRange { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public virtual Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(string processorName, Container.ChangeFeedHandler> onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task IsFeedRangePartOfAsync(FeedRange x, FeedRange y, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public FullTextPolicy FullTextPolicy { get; set; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + public VectorEmbeddingPolicy VectorEmbeddingPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public IEnumerable AccountInitializationCustomEndpoints { get; set; } + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public AvailabilityStrategy AvailabilityStrategy { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public JsonSerializerOptions UseSystemTextJsonSerializerWithOptions { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + public QueryTextMode QueryTextMode { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public abstract class CosmosLinqSerializer : CosmosSerializer + { + protected CosmosLinqSerializer(); + public abstract string SerializeMemberName(MemberInfo memberInfo); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public Nullable PayloadSizeThresholdInBytes { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + public Nullable RequestChargeThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public enum DistanceFunction + { + Cosine = 1, + DotProduct = 2, + Euclidean = 0, + } + public class Embedding : IEquatable + { + public Embedding(); + public VectorDataType DataType { get; set; } + public int Dimensions { get; set; } + public DistanceFunction DistanceFunction { get; set; } + public string Path { get; set; } + public bool Equals(Embedding that); + public void ValidateEmbeddingPath(); + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class FullTextIndexPath + { + public FullTextIndexPath(); + public string Path { get; set; } + } + public sealed class FullTextPath : IEquatable + { + public FullTextPath(); + public string Language { get; set; } + public string Path { get; set; } + public bool Equals(FullTextPath that); + public void ValidateFullTextPath(); + } + public sealed class FullTextPolicy + { + public FullTextPolicy(); + public string DefaultLanguage { get; set; } + public Collection FullTextPaths { get; set; } + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection FullTextIndexes { get; set; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + public Collection VectorIndexes { get; set; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public QueryTextMode QueryTextMode { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public enum QueryTextMode + { + All = 2, + None = 0, + ParameterizedOnly = 1, + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string AustriaEast = "Austria East"; + public const string BleuFranceCentral = "Bleu France Central"; + public const string BleuFranceSouth = "Bleu France South"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChileCentral = "Chile Central"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string DelosCloudGermanyCentral = "Delos Cloud Germany Central"; + public const string DelosCloudGermanyNorth = "Delos Cloud Germany North"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyNorth = "Germany North"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IndonesiaCentral = "Indonesia Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MalaysiaWest = "Malaysia West"; + public const string MexicoCentral = "Mexico Central"; + public const string NewZealandNorth = "New Zealand North"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SouthCentralUS2 = "South Central US 2"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SoutheastUS = "Southeast US"; + public const string SouthIndia = "South India"; + public const string SouthwestUS = "Southwest US"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string TaiwanNorth = "Taiwan North"; + public const string TaiwanNorthwest = "Taiwan Northwest"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string USSecWestCentral = "USSec West Central"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public AvailabilityStrategy AvailabilityStrategy { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } + public enum VectorDataType + { + Float32 = 0, + Int8 = 2, + Uint8 = 1, + } + public sealed class VectorEmbeddingPolicy + { + public readonly Collection Embeddings; + public VectorEmbeddingPolicy(Collection embeddings); + } + public sealed class VectorIndexPath + { + public VectorIndexPath(); + public int IndexingSearchListSize { get; set; } + public string Path { get; set; } + public int QuantizationByteSize { get; set; } + public VectorIndexType Type { get; set; } + } + public enum VectorIndexType + { + DiskANN = 1, + Flat = 0, + QuantizedFlat = 2, + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public FullTextPolicyDefinition WithFullTextPolicy(string defaultLanguage, Collection fullTextPaths); + public UniqueKeyDefinition WithUniqueKey(); + public VectorEmbeddingPolicyDefinition WithVectorEmbeddingPolicy(Collection embeddings); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithAvailabilityStrategy(AvailabilityStrategy strategy); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomAccountEndpoints(IEnumerable customAccountEndpoints); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithSystemTextJsonSerializerOptions(JsonSerializerOptions serializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class FullTextIndexDefinition + { + public FullTextIndexDefinition(T parent, Action attachCallback); + public T Attach(); + public FullTextIndexDefinition Path(string path); + } + public class FullTextPolicyDefinition + { + public FullTextPolicyDefinition(ContainerBuilder parent, string defaultLanguage, Collection fullTextPaths, Action attachCallback); + public ContainerBuilder Attach(); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public FullTextIndexDefinition> WithFullTextIndex(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + public VectorIndexDefinition> WithVectorIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } + public class VectorEmbeddingPolicyDefinition + { + public VectorEmbeddingPolicyDefinition(ContainerBuilder parent, Collection embeddings, Action attachCallback); + public ContainerBuilder Attach(); + } + public class VectorIndexDefinition + { + public VectorIndexDefinition(T parent, Action attachCallback); + public T Attach(); + public VectorIndexDefinition Path(string path, VectorIndexType indexType); + public VectorIndexDefinition WithIndexingSearchListSize(int indexingSearchListSize); + public VectorIndexDefinition WithQuantizationByteSize(int quantizationByteSize); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static int DocumentId(this object obj); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/Json/IJsonBinaryWriterExtensions.cs b/Microsoft.Azure.Cosmos/src/Json/IJsonBinaryWriterExtensions.cs index e5b943f90e..a4acea74f4 100644 --- a/Microsoft.Azure.Cosmos/src/Json/IJsonBinaryWriterExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Json/IJsonBinaryWriterExtensions.cs @@ -10,8 +10,8 @@ internal interface IJsonBinaryWriterExtensions : IJsonWriter { void WriteRawJsonValue( ReadOnlyMemory rootBuffer, - ReadOnlyMemory rawJsonValue, - bool isRootNode, + int valueOffset, + JsonBinaryEncoding.UniformArrayInfo externalArrayInfo, bool isFieldName); } } diff --git a/Microsoft.Azure.Cosmos/src/Json/IJsonWriter.cs b/Microsoft.Azure.Cosmos/src/Json/IJsonWriter.cs index 8fdd981623..d7d0cb71ec 100644 --- a/Microsoft.Azure.Cosmos/src/Json/IJsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/IJsonWriter.cs @@ -4,10 +4,11 @@ namespace Microsoft.Azure.Cosmos.Json { using System; + using System.Collections.Generic; using Microsoft.Azure.Cosmos.Core.Utf8; /// - /// Interface for all JsonWriters that know how to write jsons of a specific serialization format. + /// Common interface for all JSON writers that can write JSON in a specific serialization format. /// #if INTERNAL public @@ -87,6 +88,54 @@ interface IJsonWriter /// void WriteNullValue(); + #region Number Arrays + + /// + /// Writes an array of 8-byte unsigned integer values. + /// + /// The array of 8-byte unsigned integer values to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of 8-byte signed integer values. + /// + /// The array of 8-byte signed integer values to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of 16-byte signed integer values. + /// + /// The array of 16-byte signed integer values to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of 32-byte signed integer values. + /// + /// The array of 32-byte signed integer values to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of 64-byte signed integer values. + /// + /// The array of 64-byte signed integer values to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of single-precision floating-point numbers. + /// + /// The array of single-precision floating-point numbers to write. + void WriteNumberArray(IReadOnlyList values); + + /// + /// Writes an array of double-precision floating-point numbers. + /// + /// The array of double-precision floating-point numbers to write. + void WriteNumberArray(IReadOnlyList values); + + #endregion + + #region Extended Types + /// /// Writes an single signed byte integer to the internal buffer. /// @@ -141,6 +190,8 @@ interface IJsonWriter /// The value of the bytes to write. void WriteBinaryValue(ReadOnlySpan value); + #endregion + /// /// Gets the result of the JsonWriter. /// diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Enumerator.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Enumerator.cs index 9b05f84b03..ef7798656e 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Enumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Enumerator.cs @@ -13,57 +13,73 @@ internal static partial class JsonBinaryEncoding { public static class Enumerator { - public static IEnumerable> GetArrayItems(ReadOnlyMemory buffer) + public static IEnumerable GetArrayItems( + ReadOnlyMemory rootBuffer, + int arrayOffset, + UniformArrayInfo externalArrayInfo) { + ReadOnlyMemory buffer = rootBuffer.Slice(arrayOffset); byte typeMarker = buffer.Span[0]; - if (!JsonBinaryEncoding.TypeMarker.IsArray(typeMarker)) + + UniformArrayInfo uniformArrayInfo; + if (externalArrayInfo != null) { - throw new JsonInvalidTokenException(); + uniformArrayInfo = externalArrayInfo.NestedArrayInfo; + } + else + { + uniformArrayInfo = IsUniformArrayTypeMarker(typeMarker) ? GetUniformArrayInfo(buffer.Span) : null; } - int firstArrayItemOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker); - int arrayLength = JsonBinaryEncoding.GetValueLength(buffer.Span); - - // Scope to just the array - buffer = buffer.Slice(0, arrayLength); - - // Seek to the first array item - buffer = buffer.Slice(firstArrayItemOffset); - - while (buffer.Length != 0) + if (uniformArrayInfo != null) { - int arrayItemLength = JsonBinaryEncoding.GetValueLength(buffer.Span); - if (arrayItemLength > buffer.Length) + int itemStartOffset = arrayOffset + uniformArrayInfo.PrefixSize; + int itemEndOffset = itemStartOffset + (uniformArrayInfo.ItemSize * uniformArrayInfo.ItemCount); + for (int offset = itemStartOffset; offset < itemEndOffset; offset += uniformArrayInfo.ItemSize) + { + yield return new ArrayItem(offset, uniformArrayInfo); + } + } + else + { + if (!TypeMarker.IsArray(typeMarker)) { - // Array Item got cut off. throw new JsonInvalidTokenException(); } - // Create a buffer for that array item - ReadOnlyMemory arrayItem = buffer.Slice(0, arrayItemLength); - yield return arrayItem; + int firstArrayItemOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker); + int arrayLength = JsonBinaryEncoding.GetValueLength(buffer.Span); - // Slice off the array item - buffer = buffer.Slice(arrayItemLength); - } - } + // Scope to just the array + buffer = buffer.Slice(0, arrayLength); - public static IEnumerable> GetMutableArrayItems(Memory buffer) - { - foreach (ReadOnlyMemory readOnlyArrayItem in Enumerator.GetArrayItems(buffer)) - { - if (!MemoryMarshal.TryGetArray(readOnlyArrayItem, out ArraySegment segment)) + // Seek to the first array item + buffer = buffer.Slice(firstArrayItemOffset); + + while (buffer.Length != 0) { - throw new InvalidOperationException("failed to get array segment."); - } + int arrayItemLength = JsonBinaryEncoding.GetValueLength(buffer.Span); + if (arrayItemLength > buffer.Length) + { + // Array Item got cut off. + throw new JsonInvalidTokenException(); + } - yield return segment; + yield return new ArrayItem(arrayOffset + (arrayLength - buffer.Length), null); + + // Slice off the array item + buffer = buffer.Slice(arrayItemLength); + } } } - public static IEnumerable GetObjectProperties(ReadOnlyMemory buffer) + public static IEnumerable GetObjectProperties( + ReadOnlyMemory rootBuffer, + int objectOffset) { + ReadOnlyMemory buffer = rootBuffer.Slice(objectOffset); byte typeMarker = buffer.Span[0]; + if (!JsonBinaryEncoding.TypeMarker.IsObject(typeMarker)) { throw new JsonInvalidTokenException(); @@ -73,7 +89,7 @@ public static IEnumerable GetObjectProperties(ReadOnlyMemory GetObjectProperties(ReadOnlyMemory name = buffer.Slice(0, nameNodeLength); + int nameOffset = objectOffset + (objectLength - buffer.Length); + buffer = buffer.Slice(nameNodeLength); int valueNodeLength = JsonBinaryEncoding.GetValueLength(buffer.Span); @@ -94,57 +111,36 @@ public static IEnumerable GetObjectProperties(ReadOnlyMemory value = buffer.Slice(0, valueNodeLength); - buffer = buffer.Slice(valueNodeLength); - - yield return new ObjectProperty(name, value); - } - } - - public static IEnumerable GetMutableObjectProperties(Memory buffer) - { - foreach (ObjectProperty objectProperty in GetObjectProperties(buffer)) - { - if (!MemoryMarshal.TryGetArray(objectProperty.Name, out ArraySegment nameSegment)) - { - throw new InvalidOperationException("failed to get array segment."); - } + int valueOffset = objectOffset + (objectLength - buffer.Length); - if (!MemoryMarshal.TryGetArray(objectProperty.Value, out ArraySegment valueSegment)) - { - throw new InvalidOperationException("failed to get array segment."); - } + buffer = buffer.Slice(valueNodeLength); - yield return new MutableObjectProperty(nameSegment, valueSegment); + yield return new ObjectProperty(nameOffset, valueOffset); } } - public readonly struct ObjectProperty + public readonly struct ArrayItem { - public ObjectProperty( - ReadOnlyMemory name, - ReadOnlyMemory value) + public ArrayItem(int offset, UniformArrayInfo externalArrayInfo) { - this.Name = name; - this.Value = value; + this.Offset = offset; + this.ExternalArrayInfo = externalArrayInfo; } - public ReadOnlyMemory Name { get; } - public ReadOnlyMemory Value { get; } + public int Offset { get; } + public UniformArrayInfo ExternalArrayInfo { get; } } - public readonly struct MutableObjectProperty + public readonly struct ObjectProperty { - public MutableObjectProperty( - Memory name, - Memory value) + public ObjectProperty(int nameOffset, int valueOffset) { - this.Name = name; - this.Value = value; + this.NameOffset = nameOffset; + this.ValueOffset = valueOffset; } - public Memory Name { get; } - public Memory Value { get; } + public int NameOffset { get; } + public int ValueOffset { get; } } } } diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs index 80885d9296..e5e08321c8 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs @@ -99,7 +99,7 @@ public static class NodeTypes String, // StrR2 (Reference string of 2-byte offset) String, // StrR3 (Reference string of 3-byte offset) String, // StrR4 (Reference string of 4-byte offset) - Unknown, // 0xC7 + Number, // NumUI64 // Number Values Number, // NumUI8 @@ -109,7 +109,7 @@ public static class NodeTypes Number, // NumDbl, Float32, // Float32 Float64, // Float64 - Unknown, // 0xCF + Unknown, // Float16 (No corresponding JsonNodeType at the moment) // Other Value Types Null, // Null @@ -119,7 +119,7 @@ public static class NodeTypes Unknown, // 0xD4 Unknown, // 0xD5 Unknown, // 0xD6 - Unknown, // 0xD7 + Unknown, // UInt8 (No corresponding JsonNodeType at the moment) Int8, // Int8 Int16, // Int16 @@ -150,11 +150,11 @@ public static class NodeTypes Object, // ObjLC2 (2-byte length and count) Object, // ObjLC4 (4-byte length and count) - // Empty Range - Unknown, // 0xF0 - Unknown, // 0xF1 - Unknown, // 0xF2 - Unknown, // 0xF3 + // Array and Object Special Type Markers + Array, // ArrNumC1 Uniform number array of 1-byte item count + Array, // ArrNumC2 Uniform number array of 2-byte item count + Array, // Array of 1-byte item count of Uniform number array of 1-byte item count + Array, // Array of 2-byte item count of Uniform number array of 2-byte item count Unknown, // 0xF4 Unknown, // 0xF5 Unknown, // 0xF6 diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Numbers.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Numbers.cs index 7c768591c0..96faefdb2b 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Numbers.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Numbers.cs @@ -13,10 +13,11 @@ internal static partial class JsonBinaryEncoding /// Gets the number value from the binary reader. /// /// The buffer to read the number from. + /// The value’s external array info, if it occurs within a uniform number array. /// The number value from the binary reader. - public static Number64 GetNumberValue(ReadOnlySpan numberToken) + public static Number64 GetNumberValue(ReadOnlySpan numberToken, UniformArrayInfo uniformArrayInfo) { - if (!JsonBinaryEncoding.TryGetNumberValue(numberToken, out Number64 number64, out int bytesConsumed)) + if (!JsonBinaryEncoding.TryGetNumberValue(numberToken, uniformArrayInfo, out Number64 number64, out int _)) { throw new JsonNotNumberTokenException(); } @@ -28,10 +29,11 @@ public static Number64 GetNumberValue(ReadOnlySpan numberToken) /// Try Get NumberValue /// /// The buffer. + /// The value’s external array info, if it occurs within a uniform number array. /// The number. /// The number of bytes consumed /// Whether a number was parsed. - public static bool TryGetNumberValue(ReadOnlySpan numberToken, out Number64 number64, out int bytesConsumed) + public static bool TryGetNumberValue(ReadOnlySpan numberToken, UniformArrayInfo uniformArrayInfo, out Number64 number64, out int bytesConsumed) { number64 = 0; bytesConsumed = 0; @@ -41,69 +43,144 @@ public static bool TryGetNumberValue(ReadOnlySpan numberToken, out Number6 return false; } - byte typeMarker = numberToken[0]; - - if (JsonBinaryEncoding.TypeMarker.IsEncodedNumberLiteral(typeMarker)) - { - number64 = typeMarker - JsonBinaryEncoding.TypeMarker.LiteralIntMin; - bytesConsumed = 1; - } - else + if (uniformArrayInfo != null) { - switch (typeMarker) + switch (uniformArrayInfo.ItemTypeMarker) { - case JsonBinaryEncoding.TypeMarker.NumberUInt8: - if (numberToken.Length < (1 + 1)) + case TypeMarker.Int8: + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(sbyte); + break; + + case TypeMarker.UInt8: + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(byte); + break; + + case TypeMarker.Int16: + if (numberToken.Length < sizeof(short)) { return false; } - number64 = MemoryMarshal.Read(numberToken.Slice(1)); - bytesConsumed = 1 + 1; + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(short); break; - case JsonBinaryEncoding.TypeMarker.NumberInt16: - if (numberToken.Length < (1 + 2)) + case TypeMarker.Int32: + if (numberToken.Length < sizeof(int)) { return false; } - number64 = MemoryMarshal.Read(numberToken.Slice(1)); - bytesConsumed = 1 + 2; + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(int); break; - case JsonBinaryEncoding.TypeMarker.NumberInt32: - if (numberToken.Length < (1 + 4)) + case TypeMarker.Int64: + if (numberToken.Length < sizeof(long)) { return false; } - number64 = MemoryMarshal.Read(numberToken.Slice(1)); - bytesConsumed = 1 + 4; + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(long); break; - case JsonBinaryEncoding.TypeMarker.NumberInt64: - if (numberToken.Length < (1 + 8)) + case TypeMarker.Float16: + // Currently not supported + return false; + + case TypeMarker.Float32: + if (numberToken.Length < sizeof(float)) { return false; } - number64 = MemoryMarshal.Read(numberToken.Slice(1)); - bytesConsumed = 1 + 8; + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(float); break; - case JsonBinaryEncoding.TypeMarker.NumberDouble: - if (numberToken.Length < (1 + 8)) + case TypeMarker.Float64: + if (numberToken.Length < sizeof(double)) { return false; } - number64 = MemoryMarshal.Read(numberToken.Slice(1)); - bytesConsumed = 1 + 8; + number64 = MemoryMarshal.Read(numberToken); + bytesConsumed = sizeof(double); break; default: - throw new JsonInvalidNumberException(); + throw new JsonUnexpectedTokenException(); + } + } + else + { + byte typeMarker = numberToken[0]; + + if (JsonBinaryEncoding.TypeMarker.IsEncodedNumberLiteral(typeMarker)) + { + number64 = typeMarker - JsonBinaryEncoding.TypeMarker.LiteralIntMin; + bytesConsumed = 1; + } + else + { + switch (typeMarker) + { + case JsonBinaryEncoding.TypeMarker.NumberUInt8: + if (numberToken.Length < (1 + 1)) + { + return false; + } + + number64 = MemoryMarshal.Read(numberToken.Slice(1)); + bytesConsumed = 1 + 1; + break; + + case JsonBinaryEncoding.TypeMarker.NumberInt16: + if (numberToken.Length < (1 + 2)) + { + return false; + } + + number64 = MemoryMarshal.Read(numberToken.Slice(1)); + bytesConsumed = 1 + 2; + break; + + case JsonBinaryEncoding.TypeMarker.NumberInt32: + if (numberToken.Length < (1 + 4)) + { + return false; + } + + number64 = MemoryMarshal.Read(numberToken.Slice(1)); + bytesConsumed = 1 + 4; + break; + + case JsonBinaryEncoding.TypeMarker.NumberInt64: + if (numberToken.Length < (1 + 8)) + { + return false; + } + + number64 = MemoryMarshal.Read(numberToken.Slice(1)); + bytesConsumed = 1 + 8; + break; + + case JsonBinaryEncoding.TypeMarker.NumberDouble: + if (numberToken.Length < (1 + 8)) + { + return false; + } + + number64 = MemoryMarshal.Read(numberToken.Slice(1)); + bytesConsumed = 1 + 8; + break; + + default: + throw new JsonInvalidNumberException(); + } } } @@ -122,10 +199,13 @@ public static sbyte GetInt8Value(ReadOnlySpan int8Token) public static bool TryGetInt8Value( ReadOnlySpan int8Token, - out sbyte int8Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out sbyte int8Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( int8Token, JsonBinaryEncoding.TypeMarker.Int8, out int8Value); + } public static short GetInt16Value(ReadOnlySpan int16Token) { @@ -139,10 +219,13 @@ public static short GetInt16Value(ReadOnlySpan int16Token) public static bool TryGetInt16Value( ReadOnlySpan int16Token, - out short int16Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out short int16Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( int16Token, JsonBinaryEncoding.TypeMarker.Int16, out int16Value); + } public static int GetInt32Value(ReadOnlySpan int32Token) { @@ -156,10 +239,13 @@ public static int GetInt32Value(ReadOnlySpan int32Token) public static bool TryGetInt32Value( ReadOnlySpan int32Token, - out int int32Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out int int32Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( int32Token, JsonBinaryEncoding.TypeMarker.Int32, out int32Value); + } public static long GetInt64Value(ReadOnlySpan int64Token) { @@ -173,10 +259,13 @@ public static long GetInt64Value(ReadOnlySpan int64Token) public static bool TryGetInt64Value( ReadOnlySpan int64Token, - out long int64Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out long int64Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( int64Token, JsonBinaryEncoding.TypeMarker.Int64, out int64Value); + } public static uint GetUInt32Value(ReadOnlySpan uInt32Token) { @@ -190,10 +279,13 @@ public static uint GetUInt32Value(ReadOnlySpan uInt32Token) public static bool TryGetUInt32Value( ReadOnlySpan uInt32Token, - out uint uInt32Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out uint uInt32Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( uInt32Token, JsonBinaryEncoding.TypeMarker.UInt32, out uInt32Value); + } public static float GetFloat32Value(ReadOnlySpan float32Token) { @@ -207,10 +299,13 @@ public static float GetFloat32Value(ReadOnlySpan float32Token) public static bool TryGetFloat32Value( ReadOnlySpan float32Token, - out float float32Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out float float32Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( float32Token, JsonBinaryEncoding.TypeMarker.Float32, out float32Value); + } public static double GetFloat64Value(ReadOnlySpan float64Token) { @@ -224,9 +319,12 @@ public static double GetFloat64Value(ReadOnlySpan float64Token) public static bool TryGetFloat64Value( ReadOnlySpan float64Token, - out double float64Value) => JsonBinaryEncoding.TryGetFixedWidthValue( + out double float64Value) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( float64Token, JsonBinaryEncoding.TypeMarker.Float64, out float64Value); + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs index 8fab1e22fb..cdb409253e 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs @@ -189,7 +189,10 @@ public readonly struct TypeMarker /// public const byte ReferenceString4ByteOffset = 0xC6; - // 0xC7 + /// + /// Type marker for a 8-byte unsigned integer + /// + public const byte NumberUInt64 = 0xC7; #endregion #region [0xC8, 0xD0): Number Values @@ -228,7 +231,10 @@ public readonly struct TypeMarker /// public const byte Float64 = 0xCE; - // 0xCF + /// + /// Type marker for 16-bit floating point number. + /// + public const byte Float16 = 0xCF; #endregion #region [0xDO, 0xE0): Other Value Types @@ -255,7 +261,11 @@ public readonly struct TypeMarker // 0xD4 // 0xD5 // 0xD6 - // 0xD7 + + /// + /// The type marker for a 1-byte unsigned integer value. + /// + public const byte UInt8 = 0xD7; /// /// The type marker for a 1-byte signed integer value. @@ -299,95 +309,110 @@ public readonly struct TypeMarker #endregion #region [0xE0, 0xE8): Array Type Markers - /// /// Empty array type marker. /// - public const byte EmptyArray = 0xE0; + public const byte Arr0 = 0xE0; /// /// Single-item array type marker. /// - public const byte SingleItemArray = 0xE1; + public const byte Arr1 = 0xE1; /// /// Array of 1-byte length type marker. /// - public const byte Array1ByteLength = 0xE2; + public const byte ArrL1 = 0xE2; /// /// Array of 2-byte length type marker. /// - public const byte Array2ByteLength = 0xE3; + public const byte ArrL2 = 0xE3; /// /// Array of 4-byte length type marker. /// - public const byte Array4ByteLength = 0xE4; + public const byte ArrL4 = 0xE4; /// /// Array of 1-byte length and item count type marker. /// - public const byte Array1ByteLengthAndCount = 0xE5; + public const byte ArrLC1 = 0xE5; /// /// Array of 2-byte length and item count type marker. /// - public const byte Array2ByteLengthAndCount = 0xE6; + public const byte ArrLC2 = 0xE6; /// /// Array of 4-byte length and item count type marker. /// - public const byte Array4ByteLengthAndCount = 0xE7; + public const byte ArrLC4 = 0xE7; #endregion #region [0xE8, 0xF0): Object Type Markers /// /// Empty object type marker. /// - public const byte EmptyObject = 0xE8; + public const byte Obj0 = 0xE8; /// /// Single-property object type marker. /// - public const byte SinglePropertyObject = 0xE9; + public const byte Obj1 = 0xE9; /// /// Object of 1-byte length type marker. /// - public const byte Object1ByteLength = 0xEA; + public const byte ObjL1 = 0xEA; /// /// Object of 2-byte length type marker. /// - public const byte Object2ByteLength = 0xEB; + public const byte ObjL2 = 0xEB; /// /// Object of 4-byte length type maker. /// - public const byte Object4ByteLength = 0xEC; + public const byte ObjL4 = 0xEC; /// /// Object of 1-byte length and property count type marker. /// - public const byte Object1ByteLengthAndCount = 0xED; + public const byte ObjLC1 = 0xED; /// /// Object of 2-byte length and property count type marker. /// - public const byte Object2ByteLengthAndCount = 0xEE; + public const byte ObjLC2 = 0xEE; /// /// Object of 4-byte length and property count type marker. /// - public const byte Object4ByteLengthAndCount = 0xEF; + public const byte ObjLC4 = 0xEF; #endregion - #region [0xF0, 0xF8): Empty Range - // 0xF0 - // 0xF1 - // 0xF2 - // 0xF3 + #region [0xF0, 0xF8): Special Arrays Type Markers + /// + /// Uniform number array of 1-byte item count. + /// + public const byte ArrNumC1 = 0xF0; + + /// + /// Uniform number array of 2-byte item count. + /// + public const byte ArrNumC2 = 0xF1; + + /// + /// Array of 1-byte item count of uniform number arrays of 1-byte item count. + /// + public const byte ArrArrNumC1C1 = 0xF2; + + /// + /// Array of 2-byte item count of uniform number arrays of 2-byte item count. + /// + public const byte ArrArrNumC2C2 = 0xF3; + // 0xF4 // 0xF5 // 0xF6 @@ -693,7 +718,7 @@ public static bool IsGuid(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsEmptyArray(byte typeMarker) { - return typeMarker == EmptyArray; + return typeMarker == Arr0; } /// @@ -704,7 +729,8 @@ public static bool IsEmptyArray(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsArray(byte typeMarker) { - return InRange(typeMarker, EmptyArray, Array4ByteLengthAndCount + 1); + return InRange(typeMarker, Arr0, ArrLC4 + 1) || + InRange(typeMarker, ArrNumC1, ArrArrNumC2C2 + 1); } /// @@ -715,7 +741,7 @@ public static bool IsArray(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsEmptyObject(byte typeMarker) { - return typeMarker == EmptyObject; + return typeMarker == Obj0; } /// @@ -726,7 +752,7 @@ public static bool IsEmptyObject(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsObject(byte typeMarker) { - return InRange(typeMarker, EmptyObject, Object4ByteLengthAndCount + 1); + return InRange(typeMarker, Obj0, ObjLC4 + 1); } #endregion diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.UniformArrays.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.UniformArrays.cs new file mode 100644 index 0000000000..7d7cc5407d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.UniformArrays.cs @@ -0,0 +1,193 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Json +{ + using System; + using System.Runtime.CompilerServices; + + internal static partial class JsonBinaryEncoding + { + /// + /// Checks if the given represents a uniform array of numbers. + /// + /// The TypeMarker value to check. + /// + /// Returns true if the specified value represents a uniform array of numbers; + /// otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsUniformArrayOfNumbersTypeMarker(byte typeMarker) + { + return (typeMarker == TypeMarker.ArrNumC1) || (typeMarker == TypeMarker.ArrNumC2); + } + + /// + /// Checks if the given represents a uniform array of number arrays. + /// + /// The TypeMarker value to check. + /// + /// Returns true if the specified value represents a uniform array of number arrays; + /// otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsUniformArrayOfNumberArraysTypeMarker(byte typeMarker) + { + return (typeMarker == TypeMarker.ArrArrNumC1C1) || (typeMarker == TypeMarker.ArrArrNumC2C2); + } + + /// + /// Checks if the given represents a uniform array. + /// + /// The TypeMarker value to check. + /// + /// Returns true if the specified value represents a uniform array; + /// otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsUniformArrayTypeMarker(byte typeMarker) + { + return IsUniformArrayOfNumbersTypeMarker(typeMarker) || IsUniformArrayOfNumberArraysTypeMarker(typeMarker); + } + + public static int GetUniformArrayItemCount(ReadOnlySpan uniformArrayPrefix) + { + if (uniformArrayPrefix.IsEmpty) return default; + + byte arrayTypeMarker = uniformArrayPrefix[0]; + switch (arrayTypeMarker) + { + case TypeMarker.ArrNumC1: + // | Array TM | Number Item TM | Number Item Count | + return GetFixedSizedValue(uniformArrayPrefix.Slice(2)); + + case TypeMarker.ArrNumC2: + // | Array TM | Number Item TM | Number Item Count | + return GetFixedSizedValue(uniformArrayPrefix.Slice(2)); + + case TypeMarker.ArrArrNumC1C1: + // | Array TM | Array Item TM | Number Item TM | Number Item Count | Array Item Count | + return GetFixedSizedValue(uniformArrayPrefix.Slice(4)); + + case TypeMarker.ArrArrNumC2C2: + // | Array TM | Array Item TM | Number Item TM | Number Item Count | Array Item Count | + return GetFixedSizedValue(uniformArrayPrefix.Slice(5)); + + default: + throw new InvalidCastException($"Unexpected uniform array type marker: {arrayTypeMarker}."); + } + } + + public static int GetUniformArrayItemSize(ReadOnlySpan uniformArrayPrefix) + { + if (uniformArrayPrefix.IsEmpty) return default; + + byte arrayTypeMarker = uniformArrayPrefix[0]; + switch (arrayTypeMarker) + { + case TypeMarker.ArrNumC1: + case TypeMarker.ArrNumC2: + // | Array TM | Number Item TM | Number Item Count | + return GetValueLength(uniformArrayPrefix.Slice(1)); + + case TypeMarker.ArrArrNumC1C1: + case TypeMarker.ArrArrNumC2C2: + { + // | Array TM | Array Item TM | Number Item TM | Number Item Count | Array Item Count | + int numberItemSize = GetValueLength(uniformArrayPrefix.Slice(2)); + ushort numberItemCount = arrayTypeMarker == TypeMarker.ArrArrNumC1C1 ? + GetFixedSizedValue(uniformArrayPrefix.Slice(3)) : + GetFixedSizedValue(uniformArrayPrefix.Slice(3)); + return numberItemSize * numberItemCount; + } + + default: + throw new InvalidCastException($"Unexpected uniform array type marker: {arrayTypeMarker}."); + } + } + + public static UniformArrayInfo GetUniformArrayInfo(ReadOnlySpan arrayPrefix, bool isNested = false) + { + if (arrayPrefix.IsEmpty) + throw new ArgumentException($"{nameof(arrayPrefix)} is not empty"); + + byte arrayTypeMarker = arrayPrefix[0]; + switch (arrayTypeMarker) + { + case TypeMarker.ArrNumC1: + { + // | Array TM | Number Item TM | Number Item Count | + return new UniformArrayInfo( + itemTypeMarker: arrayPrefix[1], + prefixSize: isNested ? 0 : 3, + itemCount: GetFixedSizedValue(arrayPrefix.Slice(2)), + itemSize: ValueLengths.GetUniformNumberArrayItemSize(arrayPrefix[1])); + } + + case TypeMarker.ArrNumC2: + { + // | Array TM | Number Item TM | Number Item Count | + return new UniformArrayInfo( + itemTypeMarker: arrayPrefix[1], + prefixSize: isNested ? 0 : 4, + itemCount: GetFixedSizedValue(arrayPrefix.Slice(2)), + itemSize: ValueLengths.GetUniformNumberArrayItemSize(arrayPrefix[1])); + } + + case TypeMarker.ArrArrNumC1C1: + case TypeMarker.ArrArrNumC2C2: + { + // | Array TM | Array Item TM | Number Item TM | Number Item Count | Array Item Count | + UniformArrayInfo nestedArrayInfo = GetUniformArrayInfo(arrayPrefix.Slice(1), isNested: true); + return new UniformArrayInfo( + itemTypeMarker: arrayPrefix[1], + itemCount: arrayTypeMarker == TypeMarker.ArrArrNumC1C1 ? + GetFixedSizedValue(arrayPrefix.Slice(4)) : + GetFixedSizedValue(arrayPrefix.Slice(5)), + itemSize: nestedArrayInfo.ItemCount * nestedArrayInfo.ItemSize, + prefixSize: arrayTypeMarker == TypeMarker.ArrArrNumC1C1 ? 5 : 7, + nestedArrayInfo: nestedArrayInfo); + } + + default: + return null; + } + } + + public static bool Equals(UniformArrayInfo arrayInfo1, UniformArrayInfo arrayInfo2) + { + if (object.ReferenceEquals(arrayInfo1, arrayInfo2)) return true; + if ((arrayInfo1 == null) || (arrayInfo2 == null)) return false; + + return (arrayInfo1.ItemTypeMarker == arrayInfo2.ItemTypeMarker) && + (arrayInfo1.ItemCount == arrayInfo2.ItemCount) && + (arrayInfo1.ItemSize == arrayInfo2.ItemSize) && + (arrayInfo1.PrefixSize == arrayInfo2.PrefixSize) && + Equals(arrayInfo1.NestedArrayInfo, arrayInfo2.NestedArrayInfo); + } + + public class UniformArrayInfo + { + public byte ItemTypeMarker { get; } + public int ItemCount { get; } + public int ItemSize { get; } + public int PrefixSize { get; } + public UniformArrayInfo NestedArrayInfo { get; } + + public UniformArrayInfo( + byte itemTypeMarker, + int itemCount, + int itemSize, + int prefixSize = default, + UniformArrayInfo nestedArrayInfo = default) + { + this.ItemTypeMarker = itemTypeMarker; + this.ItemCount = itemCount; + this.ItemSize = itemSize; + this.PrefixSize = prefixSize; + this.NestedArrayInfo = nestedArrayInfo; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs index 29427c9dbd..b755d2be5f 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs @@ -27,6 +27,10 @@ private static class ValueLengths private const int CS6BL1 = -12; // 6-bit Compressed string w/ 1-byte length followed by 1-byte base char private const int Arr1 = -13; // 1-item array private const int Obj1 = -14; // 1-property object + private const int NC1 = -15; // Fixed-size numeric items of 1-byte item count + private const int NC2 = -16; // Fixed-size numeric items of 2-byte item count + private const int ANC1 = -17; // Array of fixed-size numeric items of 1-byte item count + private const int ANC2 = -18; // Array of fixed-size numeric items of 2-byte item count /// /// Lookup table for encoded value length for each TypeMarker value (0 to 255) @@ -106,7 +110,7 @@ private static class ValueLengths 3, // StrR2 (Reference string of 2-byte offset) 4, // StrR3 (Reference string of 3-byte offset) 5, // StrR4 (Reference string of 4-byte offset) - 0, // 0xC7 + 9, // NumUI64 // Number Values 2, // NumUI8 @@ -116,7 +120,7 @@ private static class ValueLengths 9, // NumDbl, 5, // Float32 9, // Float64 - 0, // 0xCF + 3, // Float16 // Other Value Types 1, // Null @@ -126,7 +130,7 @@ private static class ValueLengths 0, // 0xD4 0, // 0xD5 0, // 0xD6 - 0, // 0xD7 + 2, // UInt8 2, // Int8 3, // Int16 @@ -157,11 +161,11 @@ private static class ValueLengths LC2, // ObjLC2 (2-byte length and count) LC4, // ObjLC4 (4-byte length and count) - // Empty Range - 0, // 0xF0 - 0, // 0xF1 - 0, // 0xF2 - 0, // 0xF3 + // Array and Object Special Type Markers + NC1, // ArrNumC1 Uniform number array of 1-byte item count + NC2, // ArrNumC2 Uniform number array of 2-byte item count + ANC1, // Array of 1-byte item count of Uniform number array of 1-byte item count + ANC2, // Array of 2-byte item count of Uniform number array of 2-byte item count 0, // 0xF4 0, // 0xF5 0, // 0xF6 @@ -244,6 +248,27 @@ public static long GetValueLength(ReadOnlySpan buffer) length = TypeMarkerLength + OneByteLength + OneByteBaseChar + GetCompressedStringLength(buffer[1], numberOfBits: 6); break; + case NC1: + return 1 + 1 + 1 + (GetUniformNumberArrayItemSize(buffer[1]) * GetFixedSizedValue(buffer.Slice(2))); + case NC2: + return 1 + 1 + 2 + (GetUniformNumberArrayItemSize(buffer[1]) * GetFixedSizedValue(buffer.Slice(2))); + + case ANC1: + { + long nItemSize = GetUniformNumberArrayItemSize(buffer[2]) * GetFixedSizedValue(buffer.Slice(3)); + long nItemCount = GetFixedSizedValue(buffer.Slice(4)); + + return 1 + 3 + 1 + (nItemSize * nItemCount); + } + + case ANC2: + { + long nItemSize = GetUniformNumberArrayItemSize(buffer[2]) * GetFixedSizedValue(buffer.Slice(3)); + long nItemCount = GetFixedSizedValue(buffer.Slice(5)); + + return 1 + 4 + 2 + (nItemSize * nItemCount); + } + default: throw new ArgumentException($"Invalid variable length type marker length: {length}"); } @@ -254,6 +279,12 @@ public static long GetValueLength(ReadOnlySpan buffer) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetCompressedStringLength(int length, int numberOfBits) => ((length * numberOfBits) + 7) / 8; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetUniformNumberArrayItemSize(byte typeMarker) + { + return ValueLengths.Lookup[typeMarker] - 1; + } } } } diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.cs index bdb402249e..e8bbe4eed3 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.cs @@ -86,10 +86,13 @@ public static Guid GetGuidValue(ReadOnlySpan guidToken) public static bool TryGetGuidValue( ReadOnlySpan guidToken, - out Guid guidValue) => JsonBinaryEncoding.TryGetFixedWidthValue( + out Guid guidValue) + { + return JsonBinaryEncoding.TryGetFixedWidthValue( guidToken, JsonBinaryEncoding.TypeMarker.Guid, out guidValue); + } public static ReadOnlyMemory GetBinaryValue(ReadOnlyMemory binaryToken) { @@ -167,12 +170,12 @@ public static bool TryGetBinaryValue( } /// - /// Gets the length of a particular value given it's typemarker + /// Gets the length of a particular value given its TypeMarker. /// /// The buffer to read from as input. /// /// - Positive Value: The length of the value including its TypeMarker - /// - Negative Value: The length is encoded as an integer of size equals to abs(value) following the TypeMarker byte + /// - Negative Value: The length is encoded as an integer of size equals to abs(value) following The TypeMarker byte /// - Zero Value: The length is unknown (for instance an unassigned type marker) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -188,12 +191,12 @@ public static int GetValueLength(ReadOnlySpan buffer) } /// - /// Gets the length of a particular string given it's typemarker. + /// Gets the length of a particular string given its TypeMarker. /// /// The type marker as input /// /// - Non-Negative Value: The TypeMarker encodes the string length - /// - Negative Value: System or user dictionary encoded string, or encoded string length that follows the TypeMarker + /// - Negative Value: System or user dictionary encoded string, or encoded string length that follows The TypeMarker /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetStringLengths(byte typeMarker) @@ -204,7 +207,7 @@ public static int GetStringLengths(byte typeMarker) /// /// Gets the offset of the first item in an array or object /// - /// The typemarker as input. + /// The TypeMarker as input. /// The offset of the first item in an array or object [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetFirstValueOffset(byte typeMarker) @@ -253,7 +256,7 @@ public static void SetFixedSizedValue(Span buffer, TFixedType public static TFixedType GetFixedSizedValue(ReadOnlySpan buffer) where TFixedType : struct { - return MemoryMarshal.Cast(buffer)[0]; + return MemoryMarshal.Read(buffer); } public static string HexDump(byte[] bytes, int bytesPerLine = 16) @@ -291,7 +294,11 @@ public UInt24(byte byte1, byte byte2, byte byte3) public byte Byte2 { get; } public byte Byte3 { get; } - public static implicit operator int(UInt24 value) => (value.Byte3 << 16) | (value.Byte2 << 8) | (value.Byte1 << 0); + public static implicit operator int(UInt24 value) + { + return (value.Byte3 << 16) | (value.Byte2 << 8) | (value.Byte1 << 0); + } + public static explicit operator UInt24(int value) { if ((value & 0xFF000000) != 0) diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonNavigator.JsonBinaryNavigator.cs b/Microsoft.Azure.Cosmos/src/Json/JsonNavigator.JsonBinaryNavigator.cs index 4e6e16190d..e208796bfe 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonNavigator.JsonBinaryNavigator.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonNavigator.JsonBinaryNavigator.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Json using System.Linq; using System.Runtime.InteropServices; using Microsoft.Azure.Cosmos.Core.Utf8; + using static Microsoft.Azure.Cosmos.Json.JsonBinaryEncoding; /// /// Partial class that wraps the private JsonTextNavigator @@ -31,8 +32,7 @@ private sealed class JsonBinaryNavigator : JsonNavigator /// Initializes a new instance of the JsonBinaryNavigator class /// /// The (UTF-8) buffer to navigate. - public JsonBinaryNavigator( - ReadOnlyMemory buffer) + public JsonBinaryNavigator(ReadOnlyMemory buffer) { if (buffer.Length < 2) { @@ -49,22 +49,27 @@ public JsonBinaryNavigator( // offset for the 0x80 (128) binary serialization type marker. buffer = buffer.Slice(1); - // Only navigate the outer most json value and trim off trailing bytes + // Only navigate the outer most JSON value and trim off trailing bytes int jsonValueLength = JsonBinaryEncoding.GetValueLength(buffer.Span); if (buffer.Length < jsonValueLength) { - throw new ArgumentException("buffer is shorter than the length prefix."); + throw new ArgumentException("Input buffer is shorter than the root node length."); } - buffer = buffer.Slice(0, jsonValueLength); - this.rootNode = new BinaryNavigatorNode(buffer, JsonBinaryEncoding.NodeTypes.Lookup[buffer.Span[0]]); + JsonNodeType nodeType = JsonBinaryEncoding.NodeTypes.Lookup[buffer.Span[0]]; + this.rootNode = new BinaryNavigatorNode(nodeType, 1); } + #region IJsonNavigator + /// public override JsonSerializationFormat SerializationFormat => JsonSerializationFormat.Binary; /// - public override IJsonNavigatorNode GetRootNode() => this.rootNode; + public override IJsonNavigatorNode GetRootNode() + { + return this.rootNode; + } /// public override JsonNodeType GetNodeType(IJsonNavigatorNode node) @@ -74,16 +79,16 @@ public override JsonNodeType GetNodeType(IJsonNavigatorNode node) throw new ArgumentException($"{nameof(node)} must be a {nameof(BinaryNavigatorNode)}"); } - return binaryNavigatorNode.JsonNodeType; + return binaryNavigatorNode.NodeType; } /// public override Number64 GetNumber64Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Number64, - numberNode); - return JsonBinaryEncoding.GetNumberValue(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Number64, numberNode); + return JsonBinaryEncoding.GetNumberValue( + this.GetBufferAt(binaryNavigatorNode.Offset), + binaryNavigatorNode.ExternalArrayInfo); } /// @@ -91,97 +96,76 @@ public override bool TryGetBufferedStringValue( IJsonNavigatorNode stringNode, out Utf8Memory value) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.String, - stringNode); - + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.String, stringNode); return JsonBinaryEncoding.TryGetBufferedStringValue( this.rootBuffer, - buffer, + this.rootBuffer.Slice(binaryNavigatorNode.Offset), out value); } /// public override UtfAnyString GetStringValue(IJsonNavigatorNode stringNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.String, - stringNode); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.String, stringNode); return JsonBinaryEncoding.GetUtf8StringValue( this.rootBuffer, - buffer); + this.rootBuffer.Slice(binaryNavigatorNode.Offset)); } /// public override sbyte GetInt8Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Int8, - numberNode); - return JsonBinaryEncoding.GetInt8Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Int8, numberNode); + return JsonBinaryEncoding.GetInt8Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override short GetInt16Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Int16, - numberNode); - return JsonBinaryEncoding.GetInt16Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Int16, numberNode); + return JsonBinaryEncoding.GetInt16Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override int GetInt32Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Int32, - numberNode); - return JsonBinaryEncoding.GetInt32Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Int32, numberNode); + return JsonBinaryEncoding.GetInt32Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override long GetInt64Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Int64, - numberNode); - return JsonBinaryEncoding.GetInt64Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Int64, numberNode); + return JsonBinaryEncoding.GetInt64Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override float GetFloat32Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Float32, - numberNode); - return JsonBinaryEncoding.GetFloat32Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Float32, numberNode); + return JsonBinaryEncoding.GetFloat32Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override double GetFloat64Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Float64, - numberNode); - return JsonBinaryEncoding.GetFloat64Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Float64, numberNode); + return JsonBinaryEncoding.GetFloat64Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override uint GetUInt32Value(IJsonNavigatorNode numberNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.UInt32, - numberNode); - return JsonBinaryEncoding.GetUInt32Value(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.UInt32, numberNode); + return JsonBinaryEncoding.GetUInt32Value(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// public override Guid GetGuidValue(IJsonNavigatorNode guidNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Guid, - guidNode); - return JsonBinaryEncoding.GetGuidValue(buffer.Span); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Guid, guidNode); + return JsonBinaryEncoding.GetGuidValue(this.GetBufferAt(binaryNavigatorNode.Offset)); } /// @@ -201,51 +185,60 @@ public override bool TryGetBufferedBinaryValue( IJsonNavigatorNode binaryNode, out ReadOnlyMemory bufferedBinaryValue) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Binary, - binaryNode); - bufferedBinaryValue = JsonBinaryEncoding.GetBinaryValue(buffer); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Binary, binaryNode); + bufferedBinaryValue = JsonBinaryEncoding.GetBinaryValue(this.rootBuffer.Slice(binaryNavigatorNode.Offset)); return true; } /// public override int GetArrayItemCount(IJsonNavigatorNode arrayNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Array, - arrayNode); - byte typeMarker = buffer.Span[0]; - int firstValueOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Array, arrayNode); + ReadOnlyMemory buffer = this.rootBuffer.Slice(binaryNavigatorNode.Offset); + + int length; long count; + byte typeMarker = buffer.Span[0]; switch (typeMarker) { // Empty and Single Array - case JsonBinaryEncoding.TypeMarker.EmptyArray: + case TypeMarker.Arr0: count = 0; break; - case JsonBinaryEncoding.TypeMarker.SingleItemArray: + case TypeMarker.Arr1: count = 1; break; // Arrays with length and count prefix - case JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength).Span); + case TypeMarker.ArrLC1: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 1).Span); break; - case JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength).Span); + case TypeMarker.ArrLC2: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 2).Span); break; - case JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength).Span); + case TypeMarker.ArrLC4: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 4).Span); break; // Arrays with length prefix - case JsonBinaryEncoding.TypeMarker.Array1ByteLength: - case JsonBinaryEncoding.TypeMarker.Array2ByteLength: - case JsonBinaryEncoding.TypeMarker.Array4ByteLength: - count = JsonBinaryNavigator.GetValueCount(buffer.Slice(firstValueOffset).Span); + case TypeMarker.ArrL1: + length = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 1, length).Span); + break; + case TypeMarker.ArrL2: + length = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 2, length).Span); + break; + case TypeMarker.ArrL4: + length = (int)JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 4, length).Span); + break; + + case TypeMarker.ArrNumC1: + case TypeMarker.ArrNumC2: + case TypeMarker.ArrArrNumC1C1: + case TypeMarker.ArrArrNumC2C2: + count = JsonBinaryEncoding.GetUniformArrayItemCount(this.GetBufferAt(binaryNavigatorNode.Offset)); break; default: @@ -254,7 +247,7 @@ public override int GetArrayItemCount(IJsonNavigatorNode arrayNode) if (count > int.MaxValue) { - throw new InvalidOperationException("count can not be more than int.MaxValue"); + throw new InvalidOperationException("Array item count can not be more than 32-bit integer maximum value."); } return (int)count; @@ -263,88 +256,85 @@ public override int GetArrayItemCount(IJsonNavigatorNode arrayNode) /// public override IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNode, int index) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Array, - arrayNode); - if (index < 0) { throw new IndexOutOfRangeException(); } + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Array, arrayNode); + // TODO (brchon): We can optimize for the case where the count is serialized so we can avoid using the linear time call to TryGetValueAt(). - if (!JsonBinaryNavigator.TryGetValueAt(buffer, index, out ReadOnlyMemory arrayItem)) + IEnumerable arrayItems = Enumerator.GetArrayItems( + this.rootBuffer, + binaryNavigatorNode.Offset, + binaryNavigatorNode.ExternalArrayInfo); + + arrayItems = arrayItems.Skip(index); + if (!arrayItems.Any()) { - throw new IndexOutOfRangeException($"Tried to access index: {index} in an array."); + throw new IndexOutOfRangeException($"The specified array index '{index}' is out of range."); } - return new BinaryNavigatorNode( - arrayItem, - JsonBinaryEncoding.NodeTypes.Lookup[arrayItem.Span[0]]); + Enumerator.ArrayItem arrayItem = arrayItems.First(); + JsonNodeType nodeType = this.GetNodeType(arrayItem.Offset, arrayItem.ExternalArrayInfo); + return new BinaryNavigatorNode(nodeType, arrayItem.Offset, arrayItem.ExternalArrayInfo); } /// public override IEnumerable GetArrayItems(IJsonNavigatorNode arrayNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Array, - arrayNode); - - return this.GetArrayItemsInternal(buffer).Select((node) => (IJsonNavigatorNode)node); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Array, arrayNode); + return this.GetArrayItemsInternal(binaryNavigatorNode).Select((node) => (IJsonNavigatorNode)node); } - private IEnumerable GetArrayItemsInternal(ReadOnlyMemory buffer) => JsonBinaryEncoding.Enumerator - .GetArrayItems(buffer) - .Select(arrayItem => new BinaryNavigatorNode(arrayItem, JsonBinaryEncoding.NodeTypes.Lookup[arrayItem.Span[0]])); - /// public override int GetObjectPropertyCount(IJsonNavigatorNode objectNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Object, - objectNode); + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Object, objectNode); + ReadOnlyMemory buffer = this.rootBuffer.Slice(binaryNavigatorNode.Offset); - byte typeMarker = buffer.Span[0]; - int firstObjectPropertyOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker); + int length; long count; + byte typeMarker = buffer.Span[0]; switch (typeMarker) { // Empty and Single Object - case JsonBinaryEncoding.TypeMarker.EmptyObject: + case TypeMarker.Obj0: count = 0; break; - case JsonBinaryEncoding.TypeMarker.SinglePropertyObject: - // This number gets divided by 2 later. - count = 2; + case TypeMarker.Obj1: + count = 1; break; // Object with length and count prefix - case JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength).Span); + case TypeMarker.ObjLC1: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 1).Span); break; - case JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength).Span); + case TypeMarker.ObjLC2: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 2).Span); break; - case JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount: - count = MemoryMarshal.Read(buffer - .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength).Span); + case TypeMarker.ObjLC4: + count = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1 + 4).Span); break; // Object with length prefix - case JsonBinaryEncoding.TypeMarker.Object1ByteLength: - case JsonBinaryEncoding.TypeMarker.Object2ByteLength: - case JsonBinaryEncoding.TypeMarker.Object4ByteLength: - count = JsonBinaryNavigator.GetValueCount(buffer.Slice(firstObjectPropertyOffset).Span); + case TypeMarker.ObjL1: + length = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 1, length).Span) / 2; + break; + case TypeMarker.ObjL2: + length = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 2, length).Span) / 2; + break; + case TypeMarker.ObjL4: + length = (int)JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(1).Span); + count = JsonBinaryNavigator.GetValueCount(buffer.Slice(1 + 4, length).Span) / 2; break; default: throw new InvalidOperationException($"Unexpected object type marker: {typeMarker}"); } - // Divide by 2 since the count includes fieldname and value as seperate entities - count /= 2; if (count > int.MaxValue) { throw new InvalidOperationException("count can not be more than int.MaxValue"); @@ -359,9 +349,7 @@ public override bool TryGetObjectProperty( string propertyName, out ObjectProperty objectProperty) { - _ = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Object, - objectNode); + _ = this.GetNodeOfType(JsonNodeType.Object, objectNode); Utf8Span utf8StringPropertyName = Utf8Span.TranscodeUtf16(propertyName); foreach (ObjectProperty objectPropertyNode in this.GetObjectProperties(objectNode)) @@ -392,22 +380,13 @@ public override bool TryGetObjectProperty( /// public override IEnumerable GetObjectProperties(IJsonNavigatorNode objectNode) { - ReadOnlyMemory buffer = JsonBinaryNavigator.GetNodeOfType( - JsonNodeType.Object, - objectNode); - - return this.GetObjectPropertiesInternal(buffer) + BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.Object, objectNode); + return this.GetObjectPropertiesInternal(binaryNavigatorNode) .Select((objectPropertyInternal) => new ObjectProperty( objectPropertyInternal.NameNode, objectPropertyInternal.ValueNode)); } - private IEnumerable GetObjectPropertiesInternal(ReadOnlyMemory buffer) => JsonBinaryEncoding.Enumerator - .GetObjectProperties(buffer) - .Select(property => new ObjectPropertyInternal( - new BinaryNavigatorNode(property.Name, JsonNodeType.FieldName), - new BinaryNavigatorNode(property.Value, JsonBinaryEncoding.NodeTypes.Lookup[property.Value.Span[0]]))); - public override IJsonReader CreateReader(IJsonNavigatorNode jsonNavigatorNode) { if (!(jsonNavigatorNode is BinaryNavigatorNode binaryNavigatorNode)) @@ -415,7 +394,7 @@ public override IJsonReader CreateReader(IJsonNavigatorNode jsonNavigatorNode) throw new ArgumentException($"{nameof(jsonNavigatorNode)} must be a {nameof(BinaryNavigatorNode)}"); } - ReadOnlyMemory buffer = binaryNavigatorNode.Buffer; + ReadOnlyMemory buffer = this.rootBuffer.Slice(binaryNavigatorNode.Offset); if (!MemoryMarshal.TryGetArray(buffer, out ArraySegment segment)) { throw new InvalidOperationException("Failed to get segment"); @@ -424,72 +403,6 @@ public override IJsonReader CreateReader(IJsonNavigatorNode jsonNavigatorNode) return JsonReader.CreateBinaryFromOffset(this.rootBuffer, segment.Offset); } - private static int GetValueCount(ReadOnlySpan node) - { - int count = 0; - while (!node.IsEmpty) - { - count++; - int nodeLength = JsonBinaryEncoding.GetValueLength(node); - node = node.Slice(nodeLength); - } - - return count; - } - - private static bool TryGetValueAt( - ReadOnlyMemory arrayNode, - long index, - out ReadOnlyMemory arrayItem) - { - if (index > int.MaxValue) - { - arrayItem = default; - return false; - } - - IEnumerable> arrayItems = JsonBinaryEncoding.Enumerator.GetArrayItems(arrayNode); - arrayItems = arrayItems.Skip((int)index); - if (!arrayItems.Any()) - { - arrayItem = default; - return false; - } - - arrayItem = arrayItems.First(); - return true; - } - - private static ReadOnlyMemory GetNodeOfType( - JsonNodeType expected, - IJsonNavigatorNode node) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (!(node is BinaryNavigatorNode binaryNavigatorNode)) - { - throw new ArgumentException($"{nameof(node)} must be a {nameof(BinaryNavigatorNode)}"); - } - - ReadOnlyMemory buffer = binaryNavigatorNode.Buffer; - - if (buffer.IsEmpty) - { - throw new ArgumentException($"Node must not be empty."); - } - - JsonNodeType actual = JsonBinaryEncoding.NodeTypes.Lookup[buffer.Span[0]]; - if (actual != expected) - { - throw new ArgumentException($"Node needs to be of type {expected}."); - } - - return buffer; - } - public override void WriteNode(IJsonNavigatorNode jsonNavigatorNode, IJsonWriter jsonWriter) { if (!(jsonNavigatorNode is BinaryNavigatorNode binaryNavigatorNode)) @@ -500,21 +413,16 @@ public override void WriteNode(IJsonNavigatorNode jsonNavigatorNode, IJsonWriter bool sameEncoding = this.SerializationFormat == jsonWriter.SerializationFormat; if (sameEncoding) { - bool isFieldName = binaryNavigatorNode.JsonNodeType == JsonNodeType.FieldName; + bool isFieldName = binaryNavigatorNode.NodeType == JsonNodeType.FieldName; if (!(jsonWriter is IJsonBinaryWriterExtensions jsonBinaryWriter)) { throw new InvalidOperationException($"Expected writer to implement: {nameof(IJsonBinaryWriterExtensions)}."); } - if (!(this.rootNode is BinaryNavigatorNode binaryRootNode)) - { - throw new InvalidOperationException($"Expected {nameof(this.rootNode)} to be a {nameof(BinaryNavigatorNode)}."); - } - jsonBinaryWriter.WriteRawJsonValue( this.rootBuffer, - binaryNavigatorNode.Buffer, - isRootNode: object.ReferenceEquals(jsonNavigatorNode, this.rootNode), + valueOffset: binaryNavigatorNode.Offset, + externalArrayInfo: binaryNavigatorNode.ExternalArrayInfo, isFieldName); } else @@ -522,11 +430,35 @@ public override void WriteNode(IJsonNavigatorNode jsonNavigatorNode, IJsonWriter this.WriteToInternal(binaryNavigatorNode, jsonWriter); } } + #endregion + + private IEnumerable GetArrayItemsInternal(BinaryNavigatorNode arrayNode) + { + return Enumerator + .GetArrayItems(this.rootBuffer, arrayNode.Offset, arrayNode.ExternalArrayInfo) + .Select(arrayItem => new BinaryNavigatorNode( + this.GetNodeType(arrayItem.Offset, arrayItem.ExternalArrayInfo), + arrayItem.Offset, + arrayItem.ExternalArrayInfo)); + } + + private IEnumerable GetObjectPropertiesInternal(BinaryNavigatorNode objectNode) + { + return JsonBinaryEncoding.Enumerator + .GetObjectProperties(this.rootBuffer, objectNode.Offset) + .Select(property => new ObjectPropertyInternal( + new BinaryNavigatorNode( + JsonNodeType.FieldName, + property.NameOffset), + new BinaryNavigatorNode( + this.GetNodeType(property.ValueOffset, externalArrayInfo: default), + property.ValueOffset))); + } private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWriter jsonWriter) { - ReadOnlyMemory buffer = binaryNavigatorNode.Buffer; - JsonNodeType nodeType = binaryNavigatorNode.JsonNodeType; + ReadOnlyMemory buffer = this.rootBuffer.Slice(binaryNavigatorNode.Offset); + JsonNodeType nodeType = binaryNavigatorNode.NodeType; switch (nodeType) { @@ -544,14 +476,17 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite case JsonNodeType.Number64: { - Number64 value = JsonBinaryEncoding.GetNumberValue(buffer.Span); + Number64 value = JsonBinaryEncoding.GetNumberValue( + buffer.Span, + binaryNavigatorNode.ExternalArrayInfo); + jsonWriter.WriteNumber64Value(value); } break; case JsonNodeType.String: case JsonNodeType.FieldName: - bool fieldName = binaryNavigatorNode.JsonNodeType == JsonNodeType.FieldName; + bool fieldName = binaryNavigatorNode.NodeType == JsonNodeType.FieldName; if (JsonBinaryEncoding.TryGetBufferedStringValue( this.rootBuffer, @@ -569,9 +504,7 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite } else { - string value = JsonBinaryEncoding.GetStringValue( - this.rootBuffer, - buffer); + string value = JsonBinaryEncoding.GetStringValue(this.rootBuffer, buffer); if (fieldName) { jsonWriter.WriteFieldName(value); @@ -587,7 +520,7 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite { jsonWriter.WriteArrayStart(); - foreach (BinaryNavigatorNode arrayItem in this.GetArrayItemsInternal(buffer)) + foreach (BinaryNavigatorNode arrayItem in this.GetArrayItemsInternal(binaryNavigatorNode)) { this.WriteToInternal(arrayItem, jsonWriter); } @@ -600,7 +533,7 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite { jsonWriter.WriteObjectStart(); - foreach (ObjectPropertyInternal objectProperty in this.GetObjectPropertiesInternal(buffer)) + foreach (ObjectPropertyInternal objectProperty in this.GetObjectPropertiesInternal(binaryNavigatorNode)) { this.WriteToInternal(objectProperty.NameNode, jsonWriter); this.WriteToInternal(objectProperty.ValueNode, jsonWriter); @@ -678,19 +611,101 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite } } + private static int GetValueCount(ReadOnlySpan node) + { + int count = 0; + while (!node.IsEmpty) + { + count++; + int nodeLength = JsonBinaryEncoding.GetValueLength(node); + node = node.Slice(nodeLength); + } + + return count; + } + + private BinaryNavigatorNode GetNodeOfType( + JsonNodeType nodeType, + IJsonNavigatorNode node) + { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + if (!(node is BinaryNavigatorNode binaryNavigatorNode)) + { + throw new ArgumentException($"{nameof(node)} must be a {nameof(BinaryNavigatorNode)}."); + } + + JsonNodeType actualNodeType = this.GetNodeType(binaryNavigatorNode.Offset, binaryNavigatorNode.ExternalArrayInfo); + if (actualNodeType != nodeType) + { + throw new ArgumentException($"Node needs to be of type {nodeType}."); + } + + return binaryNavigatorNode; + } + + private ReadOnlySpan GetBufferAt(int offset) + { + return offset > 0 ? this.rootBuffer.Slice(offset).Span : default; + } + + private JsonNodeType GetNodeType(int offset, UniformArrayInfo externalArrayInfo) + { + JsonNodeType nodeType; + + if (externalArrayInfo != null) + { + switch (externalArrayInfo.ItemTypeMarker) + { + case TypeMarker.Int8: + case TypeMarker.Int16: + case TypeMarker.Int32: + case TypeMarker.Int64: + case TypeMarker.UInt8: + case TypeMarker.Float16: + case TypeMarker.Float32: + case TypeMarker.Float64: + nodeType = JsonNodeType.Number64; + break; + + case TypeMarker.ArrNumC1: + case TypeMarker.ArrNumC2: + nodeType = JsonNodeType.Array; + break; + + default: + throw new InvalidOperationException(); + } + } + else + { + byte typeMarker = this.rootBuffer.Span[offset]; + nodeType = JsonBinaryEncoding.NodeTypes.Lookup[typeMarker]; + } + + return nodeType; + } + private readonly struct BinaryNavigatorNode : IJsonNavigatorNode { public BinaryNavigatorNode( - ReadOnlyMemory buffer, - JsonNodeType jsonNodeType) + JsonNodeType nodeType, + int offset, + UniformArrayInfo externalArrayInfo = default) { - this.Buffer = buffer; - this.JsonNodeType = jsonNodeType; + this.NodeType = nodeType; + this.Offset = offset; + this.ExternalArrayInfo = externalArrayInfo; } - public ReadOnlyMemory Buffer { get; } + public JsonNodeType NodeType { get; } + + public int Offset { get; } - public JsonNodeType JsonNodeType { get; } + public UniformArrayInfo ExternalArrayInfo { get; } } private readonly struct ObjectPropertyInternal diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs b/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs index 02b11a9cc1..ad46764428 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Json using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.Azure.Cosmos.Core.Utf8; + using static Microsoft.Azure.Cosmos.Json.JsonBinaryEncoding; /// /// Partial JsonReader with a private JsonBinaryReader implementation @@ -89,7 +90,7 @@ abstract partial class JsonReader : IJsonReader JsonTokenType.String, // StrR2 (Reference string of 2-byte offset) JsonTokenType.String, // StrR3 (Reference string of 3-byte offset) JsonTokenType.String, // StrR4 (Reference string of 4-byte offset) - JsonTokenType.NotStarted, // 0xC7 + JsonTokenType.Number, // NumUI64 // Number Values JsonTokenType.Number, // NumUI8 @@ -99,7 +100,7 @@ abstract partial class JsonReader : IJsonReader JsonTokenType.Number, // NumDbl, JsonTokenType.Float32, // Float32 JsonTokenType.Float64, // Float64 - JsonTokenType.NotStarted, // 0xCF + JsonTokenType.NotStarted, // Float16 // Other Value Types JsonTokenType.Null, // Null @@ -109,7 +110,7 @@ abstract partial class JsonReader : IJsonReader JsonTokenType.NotStarted, // 0xD4 JsonTokenType.NotStarted, // 0xD5 JsonTokenType.NotStarted, // 0xD6 - JsonTokenType.NotStarted, // 0xD7 + JsonTokenType.UInt8, // UInt8 JsonTokenType.Int8, // Int8 JsonTokenType.Int16, // Int16 @@ -140,11 +141,11 @@ abstract partial class JsonReader : IJsonReader JsonTokenType.BeginObject, // ObjLC2 (2-byte length and count) JsonTokenType.BeginObject, // ObjLC4 (4-byte length and count) - // Empty Range - JsonTokenType.NotStarted, // 0xF0 - JsonTokenType.NotStarted, // 0xF1 - JsonTokenType.NotStarted, // 0xF2 - JsonTokenType.NotStarted, // 0xF3 + // Array and Object Special Type Markers + JsonTokenType.BeginArray, // ArrNumC1 Uniform number array of 1-byte item count + JsonTokenType.BeginArray, // ArrNumC2 Uniform number array of 2-byte item count + JsonTokenType.BeginArray, // Array of 1-byte item count of Uniform number array of 1-byte item count + JsonTokenType.BeginArray, // Array of 2-byte item count of Uniform number array of 2-byte item count JsonTokenType.NotStarted, // 0xF4 JsonTokenType.NotStarted, // 0xF5 JsonTokenType.NotStarted, // 0xF7 @@ -162,7 +163,7 @@ abstract partial class JsonReader : IJsonReader }.ToImmutableArray(); /// - /// JsonReader that can read from a json serialized in binary . + /// JsonReader that can read from a JSON serialized in binary . /// private sealed class JsonBinaryReader : JsonReader, ITypedJsonReader { @@ -176,7 +177,8 @@ private sealed class JsonBinaryReader : JsonReader, ITypedJsonReader /// To accommodate for this we have a progress stack to let us know how many bytes there are left to read for all levels of nesting. /// With this information we know that we are at the end of a context and can now surface an end object / array token. /// - private readonly Stack arrayAndObjectEndStack; + //private readonly Stack arrayAndObjectEndStack; + private readonly ArrayAndObjectEndStack arrayAndObjectEndStack; private readonly ReadOnlyMemory rootBuffer; @@ -211,7 +213,7 @@ internal JsonBinaryReader( readerBuffer = readerBuffer.Slice(start: 1); } - // Only navigate the outer most json value and trim off trailing bytes + // Only navigate the outer most JSON value and trim off trailing bytes int jsonValueLength = JsonBinaryEncoding.GetValueLength(readerBuffer.Span); if (readerBuffer.Length < jsonValueLength) { @@ -222,9 +224,10 @@ internal JsonBinaryReader( // offset for the 0x80 binary type marker this.jsonBinaryBuffer = new JsonBinaryMemoryReader(readerBuffer); - this.arrayAndObjectEndStack = new Stack(); + this.arrayAndObjectEndStack = new ArrayAndObjectEndStack(); } + #region IJsonReader /// public override JsonSerializationFormat SerializationFormat => JsonSerializationFormat.Binary; @@ -272,31 +275,60 @@ public override bool Read() } else if (this.JsonObjectState.CurrentDepth == 0 && this.CurrentTokenType != JsonTokenType.NotStarted) { - // There are trailing characters outside of the outter most object or array + // There are trailing characters outside of the outer most object or array throw new JsonUnexpectedTokenException(); } else { ReadOnlySpan readOnlySpan = this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span; - int nextTokenOffset = JsonBinaryEncoding.GetValueLength(readOnlySpan); - byte typeMarker = readOnlySpan[0]; - JsonTokenType jsonTokenType = JsonBinaryReader.GetJsonTokenType(typeMarker); - switch (jsonTokenType) + byte typeMarker; + int nextTokenOffset; + + UniformArrayInfo currentArrayInfo = this.arrayAndObjectEndStack.GetUniformArrayInfo(); + if (currentArrayInfo != null) + { + typeMarker = currentArrayInfo.ItemTypeMarker; + nextTokenOffset = currentArrayInfo.ItemSize; + } + else + { + typeMarker = readOnlySpan[0]; + nextTokenOffset = JsonBinaryEncoding.GetValueLength(readOnlySpan); + } + + JsonTokenType tokenType = JsonBinaryReader.GetJsonTokenType(typeMarker, currentArrayInfo); + + if (tokenType == JsonTokenType.String) { - case JsonTokenType.String when this.JsonObjectState.IsPropertyExpected: - jsonTokenType = JsonTokenType.FieldName; - break; - // If this is begin array/object token then we need to identify where array/object end token is. - // Also the next token offset is just the array type marker + length prefix + count prefix - case JsonTokenType.BeginArray: - case JsonTokenType.BeginObject: - this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + nextTokenOffset); + if (this.JsonObjectState.IsPropertyExpected) + { + tokenType = JsonTokenType.FieldName; + } + } + else if ((tokenType == JsonTokenType.BeginArray) || (tokenType == JsonTokenType.BeginObject)) + { + // If we are currently within a nested array, then the BeginArray token must be for + // a uniform number array that is within a uniform array of number arrays. + if (this.arrayAndObjectEndStack.IsWithinUniformArray()) + { + // ASSERT(tokenType == JsonTokenType.BeginArray); + this.arrayAndObjectEndStack.PushNestedArray(this.jsonBinaryBuffer.Position); + + nextTokenOffset = 0; + } + else + { + // If this is begin array/object token then we need to identify where array/object end token is. + // Also the next token offset is just the array type marker + length prefix + count prefix + UniformArrayInfo uniformArrayInfo = JsonBinaryEncoding.GetUniformArrayInfo(readOnlySpan); + this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + nextTokenOffset, uniformArrayInfo); + nextTokenOffset = JsonBinaryReader.GetArrayOrObjectPrefixLength(typeMarker); - break; + } } - this.JsonObjectState.RegisterToken(jsonTokenType); + this.JsonObjectState.RegisterToken(tokenType); this.currentTokenPosition = this.jsonBinaryBuffer.Position; this.jsonBinaryBuffer.SkipBytes(nextTokenOffset); } @@ -313,7 +345,8 @@ public override Number64 GetNumberValue() } return JsonBinaryEncoding.GetNumberValue( - this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span); + this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span, + this.arrayAndObjectEndStack.GetUniformArrayInfo()); } /// @@ -431,6 +464,30 @@ public override double GetFloat64Value() this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span); } + /// + public override Guid GetGuidValue() + { + if (this.JsonObjectState.CurrentTokenType != JsonTokenType.Guid) + { + throw new JsonNotNumberTokenException(); + } + + return JsonBinaryEncoding.GetGuidValue( + this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span); + } + + /// + public override ReadOnlyMemory GetBinaryValue() + { + if (this.JsonObjectState.CurrentTokenType != JsonTokenType.Binary) + { + throw new JsonNotNumberTokenException(); + } + + return JsonBinaryEncoding.GetBinaryValue(this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition)); + } +#endregion + /// public bool TryReadTypedJsonValueWrapper(out int typeCode) { @@ -469,29 +526,6 @@ public bool TryReadTypedJsonValueWrapper(out int typeCode) return false; } - /// - public override Guid GetGuidValue() - { - if (this.JsonObjectState.CurrentTokenType != JsonTokenType.Guid) - { - throw new JsonNotNumberTokenException(); - } - - return JsonBinaryEncoding.GetGuidValue( - this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span); - } - - /// - public override ReadOnlyMemory GetBinaryValue() - { - if (this.JsonObjectState.CurrentTokenType != JsonTokenType.Binary) - { - throw new JsonNotNumberTokenException(); - } - - return JsonBinaryEncoding.GetBinaryValue(this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition)); - } - /// public Utf8Span GetUtf8SpanValue() { @@ -507,15 +541,39 @@ public Utf8Span GetUtf8SpanValue() this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition)); } - private static JsonTokenType GetJsonTokenType(byte typeMarker) + private static JsonTokenType GetJsonTokenType(byte typeMarker, UniformArrayInfo arrayInfo) { - JsonTokenType jsonTokenType = JsonBinaryReader.TypeMarkerToTokenType[typeMarker]; - if (jsonTokenType == JsonTokenType.NotStarted) + if (arrayInfo != null) + { + switch (arrayInfo.ItemTypeMarker) + { + case TypeMarker.Int8: + case TypeMarker.UInt8: + case TypeMarker.Int16: + case TypeMarker.Int32: + case TypeMarker.Int64: + case TypeMarker.Float32: + case TypeMarker.Float64: + return JsonTokenType.Number; + + case TypeMarker.ArrNumC1: + case TypeMarker.ArrNumC2: + case TypeMarker.ArrArrNumC1C1: + case TypeMarker.ArrArrNumC2C2: + return JsonTokenType.BeginArray; + + default: + throw new JsonInvalidTokenException(); + } + } + + JsonTokenType tokenType = JsonBinaryReader.TypeMarkerToTokenType[typeMarker]; + if (tokenType == JsonTokenType.NotStarted) { throw new JsonInvalidTokenException(); } - return jsonTokenType; + return tokenType; } private static int GetArrayOrObjectPrefixLength(byte typeMarker) @@ -524,57 +582,70 @@ private static int GetArrayOrObjectPrefixLength(byte typeMarker) switch (typeMarker) { // Array Values - case JsonBinaryEncoding.TypeMarker.EmptyArray: - case JsonBinaryEncoding.TypeMarker.SingleItemArray: + case JsonBinaryEncoding.TypeMarker.Arr0: + case JsonBinaryEncoding.TypeMarker.Arr1: prefixLength = 1; break; - case JsonBinaryEncoding.TypeMarker.Array1ByteLength: + case JsonBinaryEncoding.TypeMarker.ArrL1: prefixLength = 1 + 1; break; - case JsonBinaryEncoding.TypeMarker.Array2ByteLength: + case JsonBinaryEncoding.TypeMarker.ArrL2: prefixLength = 1 + 2; break; - case JsonBinaryEncoding.TypeMarker.Array4ByteLength: + case JsonBinaryEncoding.TypeMarker.ArrL4: prefixLength = 1 + 4; break; - case JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ArrLC1: prefixLength = 1 + 1 + 1; break; - case JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ArrLC2: prefixLength = 1 + 2 + 2; break; - case JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ArrLC4: prefixLength = 1 + 4 + 4; break; // Object Values - case JsonBinaryEncoding.TypeMarker.EmptyObject: - case JsonBinaryEncoding.TypeMarker.SinglePropertyObject: + case JsonBinaryEncoding.TypeMarker.Obj0: + case JsonBinaryEncoding.TypeMarker.Obj1: prefixLength = 1; break; - case JsonBinaryEncoding.TypeMarker.Object1ByteLength: + case JsonBinaryEncoding.TypeMarker.ObjL1: prefixLength = 1 + 1; break; - case JsonBinaryEncoding.TypeMarker.Object2ByteLength: + case JsonBinaryEncoding.TypeMarker.ObjL2: prefixLength = 1 + 2; break; - case JsonBinaryEncoding.TypeMarker.Object4ByteLength: + case JsonBinaryEncoding.TypeMarker.ObjL4: prefixLength = 1 + 4; break; - case JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ObjLC1: prefixLength = 1 + 1 + 1; break; - case JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ObjLC2: prefixLength = 1 + 2 + 2; break; - case JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount: + case JsonBinaryEncoding.TypeMarker.ObjLC4: prefixLength = 1 + 4 + 4; break; + case JsonBinaryEncoding.TypeMarker.ArrNumC1: + prefixLength = 1 + 1 + 1; + break; + case JsonBinaryEncoding.TypeMarker.ArrNumC2: + prefixLength = 1 + 1 + 2; + break; + case JsonBinaryEncoding.TypeMarker.ArrArrNumC1C1: + prefixLength = 1 + 1 + 1 + 1 + 1; + break; + case JsonBinaryEncoding.TypeMarker.ArrArrNumC2C2: + prefixLength = 1 + 1 + 1 + 2 + 2; + break; + default: throw new ArgumentException($"Unknown typemarker: {typeMarker}"); } @@ -594,6 +665,81 @@ public void SkipBytes(int offset) this.position += offset; } } + + private sealed class ArrayAndObjectEndStack + { + private readonly Stack endOffsets; + private JsonBinaryEncoding.UniformArrayInfo arrayInfo; + private JsonBinaryEncoding.UniformArrayInfo nestedArrayInfo; + + public ArrayAndObjectEndStack() + { + this.endOffsets = new Stack(16); + } + + public bool Empty() + { + return this.endOffsets.Empty(); + } + + public int Peek() + { + return this.endOffsets.Peek(); + } + + public void Push(int endOffset, JsonBinaryEncoding.UniformArrayInfo arrayInfo) + { + if (this.arrayInfo != null) throw new InvalidOperationException(); + + this.endOffsets.Push(endOffset); + this.arrayInfo = arrayInfo; + } + + public void PushNestedArray(int currentOffset) + { + if (this.arrayInfo == null) throw new InvalidOperationException(); + if (this.arrayInfo.NestedArrayInfo == null) throw new InvalidOperationException(); + if (this.nestedArrayInfo != null) throw new InvalidOperationException(); + + this.endOffsets.Push(currentOffset + this.arrayInfo.ItemSize); + this.nestedArrayInfo = this.arrayInfo.NestedArrayInfo; + } + + public void Pop() + { + this.endOffsets.Pop(); + + if (this.nestedArrayInfo != null) + { + this.nestedArrayInfo = null; + } + else if (this.arrayInfo != null) + { + this.arrayInfo = null; + } + } + + public bool IsWithinUniformArray() + { + return this.arrayInfo != null; + } + + public bool IsWithinNestedUniformArray() + { + return this.nestedArrayInfo != null; + } + + public UniformArrayInfo GetUniformArrayInfo() + { + return this.nestedArrayInfo ?? this.arrayInfo; + } + + public byte GetUniformArrayItemTypeMarkerOrDefault(byte defaultValue = default) + { + UniformArrayInfo arrayInfo = this.GetUniformArrayInfo(); + return arrayInfo != null ? arrayInfo.ItemTypeMarker : defaultValue; + } + } } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonTokenType.cs b/Microsoft.Azure.Cosmos/src/Json/JsonTokenType.cs index a63b01c8f2..00879d0d12 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonTokenType.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonTokenType.cs @@ -64,7 +64,7 @@ enum JsonTokenType Null, /// - /// Corresponds to the JSON fieldname in a JSON object. + /// Corresponds to the JSON field name in a JSON object. /// FieldName, @@ -88,6 +88,11 @@ enum JsonTokenType /// Int64, + /// + /// Corresponds to an unsigned 1 byte integer + /// + UInt8, + /// /// Corresponds to an unsigned 4 byte integer /// diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriteOptions.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriteOptions.cs new file mode 100644 index 0000000000..82720b8512 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriteOptions.cs @@ -0,0 +1,34 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Json +{ + using System; + + /// + /// Specifies options for configuring the behavior of JSON writing. + /// + [FlagsAttribute] +#if INTERNAL + public +#else + internal +#endif + enum JsonWriteOptions + { + /// + /// No special options are applied. Uses default behavior for JSON writing. + /// + None = 0, + + /// + /// Enables the writing of uniform number arrays and arrays containing uniform number arrays. + /// + EnableNumberArrays = 1 << 0, + + /// + /// Enables support for writing 64-bit unsigned integers (UInt64). + /// + EnableUInt64 = 1 << 1, + } +} diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs index 6b20d99f59..a01bc33cf3 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs @@ -8,9 +8,14 @@ namespace Microsoft.Azure.Cosmos.Json using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; + using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using System.Text; using Microsoft.Azure.Cosmos.Core; using Microsoft.Azure.Cosmos.Core.Utf8; + using Microsoft.Azure.Cosmos.Linq; + using Microsoft.Azure.Cosmos.Serialization.HybridRow; + using static Microsoft.Azure.Cosmos.Json.JsonBinaryEncoding; /// /// Partial class for the JsonWriter that has a private JsonTextWriter below. @@ -22,8 +27,6 @@ namespace Microsoft.Azure.Cosmos.Json #endif abstract partial class JsonWriter : IJsonWriter { - internal bool EnableEncodedStrings { get; private set; } - /// /// Executes the provided lambda and captures a copy of the written bytes for reuse. /// The lambda is executed at a field name, and should leave the reader in a state where @@ -33,7 +36,10 @@ abstract partial class JsonWriter : IJsonWriter /// Blitted bytes. public static PreblittedBinaryJsonScope CapturePreblittedBinaryJsonScope(Action scopeWriter) { - JsonBinaryWriter jsonBinaryWriter = new JsonBinaryWriter(initialCapacity: 256, enableEncodedStrings: false); + JsonBinaryWriter jsonBinaryWriter = new JsonBinaryWriter( + initialCapacity: 256, + enableNumberArrays: false, + enableEncodedStrings: false); Contract.Requires(!jsonBinaryWriter.JsonObjectState.InArrayContext); Contract.Requires(!jsonBinaryWriter.JsonObjectState.InObjectContext); Contract.Requires(!jsonBinaryWriter.JsonObjectState.IsPropertyExpected); @@ -49,7 +55,10 @@ public static PreblittedBinaryJsonScope CapturePreblittedBinaryJsonScope(Action< /// /// Concrete implementation of that knows how to serialize to binary encoding. /// - private sealed class JsonBinaryWriter : JsonWriter, IJsonBinaryWriterExtensions, ITypedBinaryJsonWriter + private sealed class JsonBinaryWriter : + JsonWriter, + IJsonBinaryWriterExtensions, + ITypedBinaryJsonWriter { private enum RawValueType : byte { @@ -67,6 +76,9 @@ private enum RawValueType : byte Obj1, Arr, Obj, + ArrNum, + ArrArrNum, + UInt64, } private const int MaxStackAllocSize = 4 * 1024; @@ -195,11 +207,11 @@ private enum RawValueType : byte RawValueType.Obj, // RawValueType.ObjLC2 (2-byte length and count) RawValueType.Obj, // RawValueType.ObjLC4 (4-byte length and count) - // Empty Range - RawValueType.Token, // 0xF0 - RawValueType.Token, // 0xF1 - RawValueType.Token, // 0xF2 - RawValueType.Token, // 0xF3 + // Array and Object Special Type Markers + RawValueType.ArrNum, // ArrNumC1 Uniform number array of 1-byte item count + RawValueType.ArrNum, // ArrNumC2 Uniform number array of 2-byte item count + RawValueType.ArrArrNum, // Array of 1-byte item count of Uniform number array of 1-byte item count + RawValueType.ArrArrNum, // Array of 2-byte item count of Uniform number array of 2-byte item count RawValueType.Token, // 0xF4 RawValueType.Token, // 0xF5 RawValueType.Token, // 0xF6 @@ -220,23 +232,33 @@ private enum RawValueType : byte /// '$t' encoded string. /// private static readonly byte DollarTSystemString = - (byte)(JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin + (byte)(TypeMarker.SystemString1ByteLengthMin + JsonBinaryEncoding.SystemStrings.GetSystemStringId(Utf8Span.TranscodeUtf16("$t")).Value); /// /// '$v' encoded string. /// private static readonly byte DollarVSystemString = - (byte)(JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin + (byte)(TypeMarker.SystemString1ByteLengthMin + JsonBinaryEncoding.SystemStrings.GetSystemStringId(Utf8Span.TranscodeUtf16("$v")).Value); + /// + /// Determines whether to enable reference string encoding. + /// + private readonly bool enableEncodedStrings; + + /// + /// Determines whether to allow writing of uniform number arrays. + /// + private readonly bool enableNumberArrays; + /// /// Writer used to write fully materialized context to the internal stream. /// private readonly JsonBinaryMemoryWriter binaryWriter; /// - /// With binary encoding all the json elements are length prefixed, + /// 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. @@ -264,15 +286,18 @@ private enum RawValueType : byte /// Initializes a new instance of the JsonBinaryWriter class. /// /// The initial capacity to avoid intermediary allocations. - /// enable reference string encoding + /// Determines whether to enable writing of uniform number arrays. + /// Determines whether to enable reference string encoding. public JsonBinaryWriter( int initialCapacity, - bool enableEncodedStrings) + bool enableNumberArrays, + bool enableEncodedStrings = true) { - this.EnableEncodedStrings = enableEncodedStrings; + this.enableNumberArrays = enableNumberArrays; + this.enableEncodedStrings = enableEncodedStrings; this.binaryWriter = new JsonBinaryMemoryWriter(initialCapacity); this.bufferedContexts = new Stack(); - this.reservationSize = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength; + this.reservationSize = TypeMarkerLength + JsonBinaryEncoding.OneByteLength; this.sharedStrings = new List(); this.sharedStringIndexes = new ReferenceStringDictionary(); this.stringReferenceOffsets = new List(); @@ -328,7 +353,7 @@ public override void WriteNumber64Value(Number64 value) 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.binaryWriter.Write(value ? TypeMarker.True : TypeMarker.False); this.bufferedContexts.Peek().Count++; } @@ -336,7 +361,7 @@ public override void WriteBoolValue(bool value) public override void WriteNullValue() { this.JsonObjectState.RegisterToken(JsonTokenType.Null); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Null); + this.binaryWriter.Write(TypeMarker.Null); this.bufferedContexts.Peek().Count++; } @@ -344,7 +369,7 @@ public override void WriteNullValue() public override void WriteInt8Value(sbyte value) { this.JsonObjectState.RegisterToken(JsonTokenType.Int8); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int8); + this.binaryWriter.Write(TypeMarker.Int8); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -353,7 +378,7 @@ public override void WriteInt8Value(sbyte value) public override void WriteInt16Value(short value) { this.JsonObjectState.RegisterToken(JsonTokenType.Int16); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int16); + this.binaryWriter.Write(TypeMarker.Int16); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -362,7 +387,7 @@ public override void WriteInt16Value(short value) public override void WriteInt32Value(int value) { this.JsonObjectState.RegisterToken(JsonTokenType.Int32); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int32); + this.binaryWriter.Write(TypeMarker.Int32); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -371,7 +396,7 @@ public override void WriteInt32Value(int value) public override void WriteInt64Value(long value) { this.JsonObjectState.RegisterToken(JsonTokenType.Int64); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Int64); + this.binaryWriter.Write(TypeMarker.Int64); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -380,7 +405,7 @@ public override void WriteInt64Value(long value) public override void WriteFloat32Value(float value) { this.JsonObjectState.RegisterToken(JsonTokenType.Float32); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Float32); + this.binaryWriter.Write(TypeMarker.Float32); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -389,7 +414,7 @@ public override void WriteFloat32Value(float value) public override void WriteFloat64Value(double value) { this.JsonObjectState.RegisterToken(JsonTokenType.Float64); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Float64); + this.binaryWriter.Write(TypeMarker.Float64); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -398,7 +423,7 @@ public override void WriteFloat64Value(double value) public override void WriteUInt32Value(uint value) { this.JsonObjectState.RegisterToken(JsonTokenType.UInt32); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.UInt32); + this.binaryWriter.Write(TypeMarker.UInt32); this.binaryWriter.Write(value); this.bufferedContexts.Peek().Count++; } @@ -407,7 +432,7 @@ public override void WriteUInt32Value(uint value) public override void WriteGuidValue(Guid value) { this.JsonObjectState.RegisterToken(JsonTokenType.Guid); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Guid); + this.binaryWriter.Write(TypeMarker.Guid); this.binaryWriter.Write(value.ToByteArray()); this.bufferedContexts.Peek().Count++; } @@ -420,17 +445,17 @@ public override void WriteBinaryValue(ReadOnlySpan value) long length = value.Length; if ((length & ~0xFF) == 0) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Binary1ByteLength); + this.binaryWriter.Write(TypeMarker.Binary1ByteLength); this.binaryWriter.Write((byte)length); } else if ((length & ~0xFFFF) == 0) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Binary2ByteLength); + this.binaryWriter.Write(TypeMarker.Binary2ByteLength); this.binaryWriter.Write((ushort)length); } else if ((length & ~0xFFFFFFFFL) == 0) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.Binary4ByteLength); + this.binaryWriter.Write(TypeMarker.Binary4ByteLength); this.binaryWriter.Write((ulong)length); } else @@ -443,6 +468,237 @@ public override void WriteBinaryValue(ReadOnlySpan value) this.bufferedContexts.Peek().Count++; } + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.UInt8); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.UInt8); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (byte value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Int8); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Int8); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (sbyte value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Int16); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Int16); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (short value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Int32); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Int32); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (int value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Int64); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Int64); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (long value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Float32); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Float32); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (float value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + + /// + public override void WriteNumberArray(IReadOnlyList values) + { + if (!this.enableNumberArrays || (values.Count == 0) || (values.Count > ushort.MaxValue)) + { + base.WriteNumberArray(values); + } + else + { + this.JsonObjectState.RegisterToken(JsonTokenType.Null); + + if (values.Count <= byte.MaxValue) + { + this.binaryWriter.Write(TypeMarker.ArrNumC1); + this.binaryWriter.Write(TypeMarker.Float64); + this.binaryWriter.Write((byte)values.Count); + } + else + { + this.binaryWriter.Write(TypeMarker.ArrNumC2); + this.binaryWriter.Write(TypeMarker.Float64); + this.binaryWriter.Write((ushort)values.Count); + } + + foreach (double value in values) + { + this.binaryWriter.Write(value); + } + + this.bufferedContexts.Peek().Count++; + } + } + /// public override ReadOnlyMemory GetResult() { @@ -574,7 +830,7 @@ private void WriteArrayOrObjectEnd(bool isArray) this.binaryWriter.Position = typeMarkerIndex; // Write the type marker - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.EmptyArray : JsonBinaryEncoding.TypeMarker.EmptyObject); + this.binaryWriter.Write(isArray ? TypeMarker.Arr0 : TypeMarker.Obj0); } else if (count == 1) { @@ -582,28 +838,29 @@ private void WriteArrayOrObjectEnd(bool isArray) // Move the buffer back but leave one byte for the typemarker Span buffer = this.binaryWriter.BufferAsSpan; - int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength; + int bytesToWrite = TypeMarkerLength; this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.SingleItemArray : JsonBinaryEncoding.TypeMarker.SinglePropertyObject); + this.binaryWriter.Write(isArray ? TypeMarker.Arr1 : TypeMarker.Obj1); // Move the cursor forward - this.binaryWriter.Position = typeMarkerIndex + JsonBinaryEncoding.TypeMarkerLength + payloadLength; + this.binaryWriter.Position = typeMarkerIndex + TypeMarkerLength + payloadLength; } else { // Need to figure out how many bytes to encode the length and the count + int bytesToWrite; if (payloadLength <= byte.MaxValue) { bool serializeCount = isArray && (count > 16); // 1 byte length - move the buffer forward Span buffer = this.binaryWriter.BufferAsSpan; - int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + bytesToWrite = TypeMarkerLength + JsonBinaryEncoding.OneByteLength + (serializeCount ? JsonBinaryEncoding.OneByteCount : 0); this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); @@ -614,18 +871,15 @@ private void WriteArrayOrObjectEnd(bool isArray) // Write the type marker if (serializeCount) { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount); + this.binaryWriter.Write(isArray ? TypeMarker.ArrLC1 : TypeMarker.ObjLC1); this.binaryWriter.Write((byte)payloadLength); this.binaryWriter.Write((byte)count); } else { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLength : JsonBinaryEncoding.TypeMarker.Object1ByteLength); + this.binaryWriter.Write(isArray ? TypeMarker.ArrL1 : TypeMarker.ObjL1); this.binaryWriter.Write((byte)payloadLength); } - - // Move the cursor forward - this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } else if (payloadLength <= ushort.MaxValue) { @@ -640,7 +894,7 @@ private void WriteArrayOrObjectEnd(bool isArray) // Move the buffer forward Span buffer = this.binaryWriter.BufferAsSpan; - int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + bytesToWrite = TypeMarkerLength + JsonBinaryEncoding.TwoByteLength + (serializeCount ? JsonBinaryEncoding.TwoByteCount : 0); this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); @@ -651,18 +905,15 @@ private void WriteArrayOrObjectEnd(bool isArray) // Write the type marker if (serializeCount) { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount); + this.binaryWriter.Write(isArray ? TypeMarker.ArrLC2 : TypeMarker.ObjLC2); this.binaryWriter.Write((ushort)payloadLength); this.binaryWriter.Write((ushort)count); } else { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLength : JsonBinaryEncoding.TypeMarker.Object2ByteLength); + this.binaryWriter.Write(isArray ? TypeMarker.ArrL2 : TypeMarker.ObjL2); this.binaryWriter.Write((ushort)payloadLength); } - - // Move the cursor forward - this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } else { @@ -680,7 +931,7 @@ private void WriteArrayOrObjectEnd(bool isArray) // Move the buffer forward Span buffer = this.binaryWriter.BufferAsSpan; - int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + bytesToWrite = TypeMarkerLength + JsonBinaryEncoding.FourByteLength + (serializeCount ? JsonBinaryEncoding.FourByteCount : 0); this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); @@ -691,17 +942,46 @@ private void WriteArrayOrObjectEnd(bool isArray) // Write the type marker if (serializeCount) { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount); + this.binaryWriter.Write(isArray ? TypeMarker.ArrLC4 : TypeMarker.ObjLC4); this.binaryWriter.Write((uint)payloadLength); this.binaryWriter.Write((uint)count); } else { - this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLength : JsonBinaryEncoding.TypeMarker.Object4ByteLength); + this.binaryWriter.Write(isArray ? TypeMarker.ArrL4 : TypeMarker.ObjL4); this.binaryWriter.Write((uint)payloadLength); } + } - // Move the cursor forward + // For an array, attempt to convert it to a uniform number array + bool isUniformArray; + if (isArray && (payloadLength > 4) && this.enableNumberArrays) + { + this.binaryWriter.Position = typeMarkerIndex; + isUniformArray = TryWriteUniformNumberArray( + this.binaryWriter, + bytesToWrite, + payloadLength, + count); + + if (!isUniformArray) + { + this.binaryWriter.Position = typeMarkerIndex; + isUniformArray = TryWriteUniformArrayOfNumberArrays( + this.binaryWriter, + bytesToWrite, + payloadLength, + count); + } + } + else + { + isUniformArray = false; + } + + // Move the cursor forward if this is not a uniform array + if (!isUniformArray) + { this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } } @@ -715,6 +995,277 @@ private void WriteArrayOrObjectEnd(bool isArray) } } + static private bool TryWriteUniformNumberArray( + JsonBinaryMemoryWriter arrayWriter, + int byteCount, + int valueLength, + int itemCount) + { + if (arrayWriter == null) throw new ArgumentNullException(nameof(arrayWriter)); + if (byteCount <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(byteCount)); + if (valueLength <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(valueLength)); + + // Uniform arrays only support 1 and 2-byte item count + if (itemCount > ushort.MaxValue) return false; + + int floatCount = 0; + long maxValue = long.MinValue; + long minValue = long.MaxValue; + List numberValues = new List(itemCount); + + ReadOnlySpan arrayBuffer = arrayWriter.BufferAsSpan.Slice(arrayWriter.Position + byteCount, valueLength); + while (!arrayBuffer.IsEmpty) + { + if (!TypeMarker.IsNumber(arrayBuffer[0])) + { + // We encountered a non-number value, so we bail out + return false; + } + + if (JsonBinaryEncoding.TryGetNumberValue( + arrayBuffer, + uniformArrayInfo: null, + out Number64 value, + out int itemLength)) + { + numberValues.Add(value); + + if (value.IsInteger) + { + maxValue = Math.Max(maxValue, Number64.ToLong(value)); + minValue = Math.Min(minValue, Number64.ToLong(value)); + } + else + { + floatCount++; + } + } + else + { + throw new JsonUnexpectedTokenException(); + } + + arrayBuffer = arrayBuffer.Slice(itemLength); + } + + // Assert(numberValues.Count == itemCount); + // Assert(itemCount >= floatCount); + + byte itemTypeMarker; + int itemSize; + + if (floatCount > 0) + { + if (floatCount < itemCount) + { + // Not all items are floating-point values, we need to check for integer values that + // cannot be represented as floating-point values without losing precision. + + long nMaxAbsValue = Math.Max(Math.Abs(minValue), Math.Abs(maxValue)); + if (nMaxAbsValue > (1L << 53)) return false; + } + + itemTypeMarker = TypeMarker.Float64; + itemSize = sizeof(double); + } + else + { + if ((minValue >= 0) && (maxValue <= byte.MaxValue)) + { + itemTypeMarker = TypeMarker.UInt8; + itemSize = sizeof(byte); + } + else if ((minValue >= sbyte.MinValue) && (maxValue <= sbyte.MaxValue)) + { + itemTypeMarker = TypeMarker.Int8; + itemSize = sizeof(sbyte); + } + else if ((minValue >= short.MinValue) && (maxValue <= short.MaxValue)) + { + itemTypeMarker = TypeMarker.Int16; + itemSize = sizeof(short); + } + else if ((minValue >= int.MinValue) && (maxValue <= int.MaxValue)) + { + itemTypeMarker = TypeMarker.Int32; + itemSize = sizeof(int); + } + else + { + itemTypeMarker = TypeMarker.Int64; + itemSize = sizeof(long); + } + } + + int newByteCount = 1 /* item TypeMarker */ + (itemCount <= byte.MaxValue ? 1 : 2) /* item count */; + int newLength = 1 + newByteCount + (itemCount * itemSize); + int oldLength = 1 + byteCount + valueLength; + + // Verify whether writing a uniform number array is beneficial + if (newLength > oldLength) + { + return false; + } + + if (itemCount <= byte.MaxValue) + { + arrayWriter.Write(TypeMarker.ArrNumC1); + arrayWriter.Write(itemTypeMarker); + arrayWriter.Write((byte)itemCount); + } + else + { + arrayWriter.Write(TypeMarker.ArrNumC2); + arrayWriter.Write(itemTypeMarker); + arrayWriter.Write((short)itemCount); + } + + // Write the uniform number array beginning at the start offset + switch (itemTypeMarker) + { + case TypeMarker.Int8: + foreach (Number64 value in numberValues) + { + arrayWriter.Write((sbyte)Number64.ToLong(value)); + } + break; + case TypeMarker.UInt8: + foreach (Number64 value in numberValues) + { + arrayWriter.Write((byte)Number64.ToLong(value)); + } + break; + case TypeMarker.Int16: + foreach (Number64 value in numberValues) + { + arrayWriter.Write((short)Number64.ToLong(value)); + } + break; + case TypeMarker.Int32: + foreach (Number64 value in numberValues) + { + arrayWriter.Write((int)Number64.ToLong(value)); + } + break; + case TypeMarker.Int64: + foreach (Number64 value in numberValues) + { + arrayWriter.Write(Number64.ToLong(value)); + } + break; + case TypeMarker.Float16: + // Currently not supported + throw new InvalidOperationException(); + case TypeMarker.Float32: + foreach (Number64 value in numberValues) + { + arrayWriter.Write((float)Number64.ToDouble(value)); + } + break; + case TypeMarker.Float64: + foreach (Number64 value in numberValues) + { + arrayWriter.Write(Number64.ToDouble(value)); + } + break; + default: + throw new InvalidOperationException(); + } + + return true; + } + + static private bool TryWriteUniformArrayOfNumberArrays( + JsonBinaryMemoryWriter arrayWriter, + int byteCount, + int valueLength, + int itemCount) + { + if (arrayWriter == null) throw new ArgumentNullException(nameof(arrayWriter)); + if (byteCount <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(byteCount)); + if (valueLength <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(valueLength)); + + // Uniform arrays only support 1 and 2-byte item count + if (itemCount > ushort.MaxValue) return false; + if (itemCount < 2) return false; + + UniformArrayInfo commonArrayInfo = default; + int commonArrayLength = 0; + + ReadOnlySpan arrayBuffer = arrayWriter.BufferAsSpan.Slice(arrayWriter.Position + byteCount, valueLength); + while (!arrayBuffer.IsEmpty) + { + UniformArrayInfo numberArrayInfo = GetUniformArrayInfo(arrayBuffer, isNested: false); + if (numberArrayInfo == default) + { + // Not a uniform number array + return false; + } + + if (numberArrayInfo.NestedArrayInfo != default) + { + // Already an array of uniform number arrays + return false; + } + + if (commonArrayInfo == null) + { + commonArrayInfo = numberArrayInfo; + commonArrayLength = commonArrayInfo.PrefixSize + (commonArrayInfo.ItemCount * commonArrayInfo.ItemSize); + } + + if (!JsonBinaryEncoding.Equals(numberArrayInfo, commonArrayInfo)) + { + // A uniform number array that is different from the common one so far + return false; + } + + arrayBuffer = arrayBuffer.Slice(commonArrayLength); + } + + bool oneByteCount = (commonArrayInfo.ItemCount <= byte.MaxValue) && (itemCount <= byte.MaxValue); + int newByteCount = oneByteCount ? 5 : 7; + + // This condition should never happen but still needs to be covered + if (newByteCount > (byteCount + (commonArrayInfo.PrefixSize * 2))) + { + return false; + } + + int initialPosition = arrayWriter.Position; + arrayWriter.Position += newByteCount; + + ReadOnlySpan arrayItems = arrayWriter.BufferAsSpan.Slice(initialPosition + byteCount, valueLength); + while (!arrayItems.IsEmpty) + { + arrayWriter.Write(arrayItems.Slice(commonArrayInfo.PrefixSize, commonArrayLength - commonArrayInfo.PrefixSize)); + arrayItems = arrayItems.Slice(commonArrayLength); + } + + int finalPosition = arrayWriter.Position; + arrayWriter.Position = initialPosition; + + if (oneByteCount) + { + arrayWriter.Write(TypeMarker.ArrArrNumC1C1); + arrayWriter.Write(TypeMarker.ArrNumC1); + arrayWriter.Write(commonArrayInfo.ItemTypeMarker); + arrayWriter.Write((byte)commonArrayInfo.ItemCount); + arrayWriter.Write((byte)itemCount); + } + else + { + arrayWriter.Write(TypeMarker.ArrArrNumC2C2); + arrayWriter.Write(TypeMarker.ArrNumC2); + arrayWriter.Write(commonArrayInfo.ItemTypeMarker); + arrayWriter.Write((ushort)commonArrayInfo.ItemCount); + arrayWriter.Write((ushort)itemCount); + } + + arrayWriter.Position = finalPosition; + return true; + } + private void MoveBuffer( Span buffer, int payloadIndex, @@ -757,7 +1308,7 @@ private void FixReferenceStringOffsets(Span binaryWriterRawBuffer) Span offsetBuffer = binaryWriterRawBuffer.Slice(stringReferenceOffset + 1); switch (typeMarker) { - case JsonBinaryEncoding.TypeMarker.ReferenceString1ByteOffset: + case TypeMarker.ReferenceString1ByteOffset: { byte stringIndex = offsetBuffer[0]; SharedStringValue sharedStringValue = this.sharedStrings[stringIndex]; @@ -765,7 +1316,7 @@ private void FixReferenceStringOffsets(Span binaryWriterRawBuffer) break; } - case JsonBinaryEncoding.TypeMarker.ReferenceString2ByteOffset: + case TypeMarker.ReferenceString2ByteOffset: { ushort stringIndex = JsonBinaryEncoding.GetFixedSizedValue(offsetBuffer); SharedStringValue sharedStringValue = this.sharedStrings[stringIndex]; @@ -773,7 +1324,7 @@ private void FixReferenceStringOffsets(Span binaryWriterRawBuffer) break; } - case JsonBinaryEncoding.TypeMarker.ReferenceString3ByteOffset: + case TypeMarker.ReferenceString3ByteOffset: { JsonBinaryEncoding.UInt24 stringIndex = JsonBinaryEncoding.GetFixedSizedValue(offsetBuffer); @@ -784,7 +1335,7 @@ private void FixReferenceStringOffsets(Span binaryWriterRawBuffer) break; } - case JsonBinaryEncoding.TypeMarker.ReferenceString4ByteOffset: + case TypeMarker.ReferenceString4ByteOffset: { int stringIndex = JsonBinaryEncoding.GetFixedSizedValue(offsetBuffer); SharedStringValue sharedStringValue = this.sharedStrings[stringIndex]; @@ -803,7 +1354,7 @@ private void FixReferenceStringOffsets(Span binaryWriterRawBuffer) private void WriteFieldNameOrString(bool isFieldName, Utf8Span utf8Span) { - this.binaryWriter.EnsureRemainingBufferSpace(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength + utf8Span.Length); + this.binaryWriter.EnsureRemainingBufferSpace(TypeMarkerLength + JsonBinaryEncoding.FourByteLength + utf8Span.Length); this.JsonObjectState.RegisterToken(isFieldName ? JsonTokenType.FieldName : JsonTokenType.String); if (JsonBinaryEncoding.TryGetEncodedStringTypeMarker( @@ -825,14 +1376,14 @@ private void WriteFieldNameOrString(bool isFieldName, Utf8Span utf8Span) throw new InvalidOperationException($"Unable to serialize a {nameof(JsonBinaryEncoding.MultiByteTypeMarker)} of length: {multiByteTypeMarker.Length}"); } } - else if (this.EnableEncodedStrings + else if (this.enableEncodedStrings && isFieldName && (utf8Span.Length >= MinReferenceStringLength) && this.TryRegisterStringValue(utf8Span)) { // Work is done in the check } - else if (this.EnableEncodedStrings + else if (this.enableEncodedStrings && !isFieldName && (utf8Span.Length == JsonBinaryEncoding.GuidLength) && JsonBinaryEncoding.TryEncodeGuidString(utf8Span.Span, this.binaryWriter.Cursor)) @@ -840,26 +1391,26 @@ private void WriteFieldNameOrString(bool isFieldName, Utf8Span utf8Span) // Encoded value as guid string this.binaryWriter.Position += JsonBinaryEncoding.EncodedGuidLength; } - else if (this.EnableEncodedStrings + else if (this.enableEncodedStrings && !isFieldName && (utf8Span.Length == JsonBinaryEncoding.GuidWithQuotesLength) && (utf8Span.Span[0] == '"') && (utf8Span.Span[JsonBinaryEncoding.GuidWithQuotesLength - 1] == '"') && JsonBinaryEncoding.TryEncodeGuidString(utf8Span.Span.Slice(start: 1), this.binaryWriter.Cursor) - && (this.binaryWriter.Cursor[0] == JsonBinaryEncoding.TypeMarker.LowercaseGuidString)) + && (this.binaryWriter.Cursor[0] == TypeMarker.LowercaseGuidString)) { // Encoded value as lowercase double quote guid - this.binaryWriter.Cursor[0] = JsonBinaryEncoding.TypeMarker.DoubleQuotedLowercaseGuidString; + this.binaryWriter.Cursor[0] = TypeMarker.DoubleQuotedLowercaseGuidString; this.binaryWriter.Position += JsonBinaryEncoding.EncodedGuidLength; } - else if (this.EnableEncodedStrings + else if (this.enableEncodedStrings && !isFieldName && JsonBinaryEncoding.TryEncodeCompressedString(utf8Span.Span, this.binaryWriter.Cursor, out int bytesWritten)) { // Encoded value as a compressed string this.binaryWriter.Position += bytesWritten; } - else if (this.EnableEncodedStrings + else if (this.enableEncodedStrings && !isFieldName && (utf8Span.Length >= MinReferenceStringLength) && (utf8Span.Length <= MaxReferenceStringLength) @@ -867,7 +1418,7 @@ private void WriteFieldNameOrString(bool isFieldName, Utf8Span utf8Span) { // Work is done in the check } - else if (JsonBinaryEncoding.TypeMarker.TryGetEncodedStringLengthTypeMarker(utf8Span.Length, out byte typeMarker)) + else if (TypeMarker.TryGetEncodedStringLengthTypeMarker(utf8Span.Length, out byte typeMarker)) { // Write with type marker that encodes the length this.binaryWriter.Write(typeMarker); @@ -876,20 +1427,20 @@ private void WriteFieldNameOrString(bool isFieldName, Utf8Span utf8Span) // Just write it out as a regular string with type marker and length prefix else if (utf8Span.Length < byte.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String1ByteLength); + this.binaryWriter.Write(TypeMarker.String1ByteLength); this.binaryWriter.Write((byte)utf8Span.Length); this.binaryWriter.Write(utf8Span.Span); } else if (utf8Span.Length < ushort.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String2ByteLength); + this.binaryWriter.Write(TypeMarker.String2ByteLength); this.binaryWriter.Write((ushort)utf8Span.Length); this.binaryWriter.Write(utf8Span.Span); } else { // (utf8String.Length < uint.MaxValue) - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.String4ByteLength); + this.binaryWriter.Write(TypeMarker.String4ByteLength); this.binaryWriter.Write((uint)utf8Span.Length); this.binaryWriter.Write(utf8Span.Span); } @@ -931,22 +1482,22 @@ private bool TryRegisterStringValue(Utf8Span utf8Span) if (sharedString.MaxOffset <= byte.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.ReferenceString1ByteOffset); + this.binaryWriter.Write(TypeMarker.ReferenceString1ByteOffset); this.binaryWriter.Write((byte)hashAndIndex.index); } else if (sharedString.MaxOffset <= ushort.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.ReferenceString2ByteOffset); + this.binaryWriter.Write(TypeMarker.ReferenceString2ByteOffset); this.binaryWriter.Write((ushort)hashAndIndex.index); } else if (sharedString.MaxOffset <= JsonBinaryEncoding.UInt24.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.ReferenceString3ByteOffset); + this.binaryWriter.Write(TypeMarker.ReferenceString3ByteOffset); this.binaryWriter.Write((JsonBinaryEncoding.UInt24)(int)hashAndIndex.index); } else if (sharedString.MaxOffset <= int.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.ReferenceString4ByteOffset); + this.binaryWriter.Write(TypeMarker.ReferenceString4ByteOffset); this.binaryWriter.Write((int)hashAndIndex.index); } else @@ -960,9 +1511,9 @@ private bool TryRegisterStringValue(Utf8Span utf8Span) private void WriteIntegerInternal(long value) { this.JsonObjectState.RegisterToken(JsonTokenType.Number); - if (JsonBinaryEncoding.TypeMarker.IsEncodedNumberLiteral(value)) + if (TypeMarker.IsEncodedNumberLiteral(value)) { - this.binaryWriter.Write((byte)(JsonBinaryEncoding.TypeMarker.LiteralIntMin + value)); + this.binaryWriter.Write((byte)(TypeMarker.LiteralIntMin + value)); } else { @@ -971,22 +1522,22 @@ private void WriteIntegerInternal(long value) // Non-negative Number if (value <= byte.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberUInt8); + this.binaryWriter.Write(TypeMarker.NumberUInt8); this.binaryWriter.Write((byte)value); } else if (value <= short.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt16); + this.binaryWriter.Write(TypeMarker.NumberInt16); this.binaryWriter.Write((short)value); } else if (value <= int.MaxValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt32); + this.binaryWriter.Write(TypeMarker.NumberInt32); this.binaryWriter.Write((int)value); } else { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt64); + this.binaryWriter.Write(TypeMarker.NumberInt64); this.binaryWriter.Write(value); } } @@ -995,17 +1546,17 @@ private void WriteIntegerInternal(long value) // Negative Number if (value < int.MinValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt64); + this.binaryWriter.Write(TypeMarker.NumberInt64); this.binaryWriter.Write(value); } else if (value < short.MinValue) { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt32); + this.binaryWriter.Write(TypeMarker.NumberInt32); this.binaryWriter.Write((int)value); } else { - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberInt16); + this.binaryWriter.Write(TypeMarker.NumberInt16); this.binaryWriter.Write((short)value); } } @@ -1015,149 +1566,181 @@ private void WriteIntegerInternal(long value) private void WriteDoubleInternal(double value) { this.JsonObjectState.RegisterToken(JsonTokenType.Number); - this.binaryWriter.Write(JsonBinaryEncoding.TypeMarker.NumberDouble); + this.binaryWriter.Write(TypeMarker.NumberDouble); this.binaryWriter.Write(value); } public void WriteRawJsonValue( ReadOnlyMemory rootBuffer, - ReadOnlyMemory rawJsonValue, - bool isRootNode, + int valueOffset, + UniformArrayInfo externalArrayInfo, bool isFieldName) { - if (isRootNode && (this.binaryWriter.Position == 1)) - { - // Other that whether or not this is a field name, the type of the value does not matter here - this.JsonObjectState.RegisterToken(isFieldName ? JsonTokenType.FieldName : JsonTokenType.String); - this.binaryWriter.Write(rawJsonValue.Span); - if (!isFieldName) - { - this.bufferedContexts.Peek().Count++; - } - } - else - { - this.ForceRewriteRawJsonValue(rootBuffer, rawJsonValue, isFieldName); - } + this.ForceRewriteRawJsonValue(rootBuffer, valueOffset, externalArrayInfo, isFieldName); } private void ForceRewriteRawJsonValue( ReadOnlyMemory rootBuffer, - ReadOnlyMemory rawJsonValue, + int valueOffset, + UniformArrayInfo externalArrayInfo, bool isFieldName) { + ReadOnlyMemory rawJsonValue = rootBuffer.Slice(valueOffset); byte typeMarker = rawJsonValue.Span[0]; - RawValueType rawType = (RawValueType)RawValueTypes[typeMarker]; - switch (rawType) + + if (externalArrayInfo != null) { - case RawValueType.Token: - { - int valueLength = JsonBinaryEncoding.GetValueLength(rawJsonValue.Span); + this.WriteRawUniformArrayItem(rawJsonValue.Span, externalArrayInfo); + } + else + { + RawValueType rawType = (RawValueType)RawValueTypes[typeMarker]; - rawJsonValue = rawJsonValue.Slice(start: 0, length: valueLength); + // If the writer supports uniform-number arrays then we treat them as a value token + if (this.enableEncodedStrings && ((rawType == RawValueType.ArrNum) || (rawType == RawValueType.ArrArrNum))) + { + rawType = RawValueType.Token; + } - // We only care if the type is a fieldname or not - this.JsonObjectState.RegisterToken(isFieldName ? JsonTokenType.FieldName : JsonTokenType.String); + switch (rawType) + { + case RawValueType.Token: + { + int valueLength = JsonBinaryEncoding.GetValueLength(rawJsonValue.Span); - this.binaryWriter.Write(rawJsonValue.Span); + rawJsonValue = rawJsonValue.Slice(start: 0, length: valueLength); - if (!isFieldName) - { - this.bufferedContexts.Peek().Count++; - } - } - break; + // We only care if the type is a field name or not + this.JsonObjectState.RegisterToken(isFieldName ? JsonTokenType.FieldName : JsonTokenType.String); - case RawValueType.StrUsr: - case RawValueType.StrEncLen: - case RawValueType.StrL1: - case RawValueType.StrL2: - case RawValueType.StrL4: - this.WriteRawStringValue(rawType, rawJsonValue, isFieldName); - break; + this.binaryWriter.Write(rawJsonValue.Span); - case RawValueType.StrR1: - this.ForceRewriteRawJsonValue( - rootBuffer, - rootBuffer.Slice(JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span)), - isFieldName); - break; - case RawValueType.StrR2: - this.ForceRewriteRawJsonValue( - rootBuffer, - rootBuffer.Slice(JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span)), - isFieldName); - break; - case RawValueType.StrR3: - this.ForceRewriteRawJsonValue( - rootBuffer, - rootBuffer.Slice(JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span)), - isFieldName); - break; - case RawValueType.StrR4: - this.ForceRewriteRawJsonValue( - rootBuffer, - rootBuffer.Slice(JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span)), - isFieldName); - break; + if (!isFieldName) + { + this.bufferedContexts.Peek().Count++; + } + } + break; - case RawValueType.Arr1: - { - this.JsonObjectState.RegisterToken(JsonTokenType.BeginArray); + case RawValueType.StrUsr: + case RawValueType.StrEncLen: + case RawValueType.StrL1: + case RawValueType.StrL2: + case RawValueType.StrL4: + this.WriteRawStringValue(rawType, rawJsonValue, isFieldName); + break; - this.binaryWriter.Write(typeMarker); + case RawValueType.StrR1: + this.ForceRewriteRawJsonValue( + rootBuffer, + JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span), + default, + isFieldName); + break; + case RawValueType.StrR2: + this.ForceRewriteRawJsonValue( + rootBuffer, + JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span), + default, + isFieldName); + break; + case RawValueType.StrR3: + this.ForceRewriteRawJsonValue( + rootBuffer, + JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span), + default, + isFieldName); + break; + case RawValueType.StrR4: + this.ForceRewriteRawJsonValue( + rootBuffer, + JsonBinaryEncoding.GetFixedSizedValue(rawJsonValue.Slice(start: 1).Span), + default, + isFieldName); + break; - this.ForceRewriteRawJsonValue(rootBuffer, rawJsonValue.Slice(start: 1), isFieldName: false); + case RawValueType.Arr1: + { + this.JsonObjectState.RegisterToken(JsonTokenType.BeginArray); - this.JsonObjectState.RegisterToken(JsonTokenType.EndArray); - } - break; + this.binaryWriter.Write(typeMarker); - case RawValueType.Obj1: - { - this.JsonObjectState.RegisterToken(JsonTokenType.BeginObject); + this.ForceRewriteRawJsonValue( + rootBuffer, + valueOffset: valueOffset + 1, + externalArrayInfo: default, + isFieldName: false); - this.binaryWriter.Write(typeMarker); + this.JsonObjectState.RegisterToken(JsonTokenType.EndArray); + } + break; - this.ForceRewriteRawJsonValue(rootBuffer, rawJsonValue.Slice(start: 1), isFieldName: true); + case RawValueType.Obj1: + { + this.JsonObjectState.RegisterToken(JsonTokenType.BeginObject); - int nameLength = JsonBinaryEncoding.GetValueLength(rawJsonValue.Slice(start: 1).Span); + this.binaryWriter.Write(typeMarker); - this.ForceRewriteRawJsonValue(rootBuffer, rawJsonValue.Slice(start: 1 + nameLength), isFieldName: false); + this.ForceRewriteRawJsonValue( + rootBuffer, + valueOffset: valueOffset + 1, + externalArrayInfo: default, + isFieldName: true); - this.JsonObjectState.RegisterToken(JsonTokenType.EndObject); - } - break; + int nameLength = JsonBinaryEncoding.GetValueLength(rawJsonValue.Slice(start: 1).Span); - case RawValueType.Arr: - { - this.WriteArrayStart(); + this.ForceRewriteRawJsonValue( + rootBuffer, + valueOffset: valueOffset + 1 + nameLength, + externalArrayInfo: default, + isFieldName: false); - foreach (ReadOnlyMemory arrayItem in JsonBinaryEncoding.Enumerator.GetArrayItems(rawJsonValue)) - { - this.ForceRewriteRawJsonValue(rootBuffer, arrayItem, isFieldName); + this.JsonObjectState.RegisterToken(JsonTokenType.EndObject); } + break; - this.WriteArrayEnd(); - } - break; + case RawValueType.Arr: + { + this.WriteArrayStart(); - case RawValueType.Obj: - { - this.WriteObjectStart(); + foreach (JsonBinaryEncoding.Enumerator.ArrayItem arrayItem in JsonBinaryEncoding.Enumerator.GetArrayItems(rootBuffer, valueOffset, externalArrayInfo)) + { + this.ForceRewriteRawJsonValue( + rootBuffer, + arrayItem.Offset, + arrayItem.ExternalArrayInfo, + isFieldName); + } - foreach (JsonBinaryEncoding.Enumerator.ObjectProperty property in JsonBinaryEncoding.Enumerator.GetObjectProperties(rawJsonValue)) + this.WriteArrayEnd(); + } + break; + + case RawValueType.Obj: { - this.ForceRewriteRawJsonValue(rootBuffer, property.Name, isFieldName: true); - this.ForceRewriteRawJsonValue(rootBuffer, property.Value, isFieldName: false); + this.WriteObjectStart(); + + foreach (JsonBinaryEncoding.Enumerator.ObjectProperty property in JsonBinaryEncoding.Enumerator.GetObjectProperties(rootBuffer, valueOffset)) + { + this.ForceRewriteRawJsonValue(rootBuffer, property.NameOffset, externalArrayInfo: default, isFieldName: true); + this.ForceRewriteRawJsonValue(rootBuffer, property.ValueOffset, externalArrayInfo: default, isFieldName: false); + } + + this.WriteObjectEnd(); } + break; - this.WriteObjectEnd(); - } - break; + case RawValueType.ArrNum: + this.WriteRawNumberArray(rawJsonValue.Span, GetUniformArrayInfo(rawJsonValue.Span)); + break; - default: - throw new InvalidOperationException($"Unknown {nameof(RawValueType)} {rawType}."); + case RawValueType.ArrArrNum: + this.WriteRawNumberArrayArray(rawJsonValue.Span, GetUniformArrayInfo(rawJsonValue.Span)); + break; + + default: + throw new InvalidOperationException($"Unknown {nameof(RawValueType)} {rawType}."); + } } } @@ -1178,33 +1761,33 @@ private void WriteRawStringValue(RawValueType rawValueType, ReadOnlyMemory break; case RawValueType.StrEncLen: - long encodedStringLength = JsonBinaryEncoding.TypeMarker.GetEncodedStringLength(buffer.Span[0]); + long encodedStringLength = TypeMarker.GetEncodedStringLength(buffer.Span[0]); if (encodedStringLength > int.MaxValue) { throw new InvalidOperationException("string is too long."); } - rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: JsonBinaryEncoding.TypeMarkerLength, (int)encodedStringLength).Span); + rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: TypeMarkerLength, (int)encodedStringLength).Span); break; case RawValueType.StrL1: - byte oneByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(JsonBinaryEncoding.TypeMarkerLength).Span); - rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: JsonBinaryEncoding.TypeMarkerLength + sizeof(byte), oneByteLength).Span); + byte oneByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(TypeMarkerLength).Span); + rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: TypeMarkerLength + sizeof(byte), oneByteLength).Span); break; case RawValueType.StrL2: - ushort twoByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(JsonBinaryEncoding.TypeMarkerLength).Span); - rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: JsonBinaryEncoding.TypeMarkerLength + sizeof(ushort), twoByteLength).Span); + ushort twoByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(TypeMarkerLength).Span); + rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: TypeMarkerLength + sizeof(ushort), twoByteLength).Span); break; case RawValueType.StrL4: - uint fourByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(JsonBinaryEncoding.TypeMarkerLength).Span); + uint fourByteLength = JsonBinaryEncoding.GetFixedSizedValue(buffer.Slice(TypeMarkerLength).Span); if (fourByteLength > int.MaxValue) { throw new InvalidOperationException("string is too long."); } - rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: JsonBinaryEncoding.TypeMarkerLength + sizeof(uint), (int)fourByteLength).Span); + rawStringValue = Utf8Span.UnsafeFromUtf8BytesNoValidation(buffer.Slice(start: TypeMarkerLength + sizeof(uint), (int)fourByteLength).Span); break; default: @@ -1214,6 +1797,130 @@ private void WriteRawStringValue(RawValueType rawValueType, ReadOnlyMemory this.WriteFieldNameOrString(isFieldName, rawStringValue); } + private void WriteRawUniformArrayItem( + ReadOnlySpan rawValue, + UniformArrayInfo arrayInfo) + { + if (arrayInfo == null) throw new ArgumentNullException(nameof(arrayInfo)); + + switch (arrayInfo.ItemTypeMarker) + { + case TypeMarker.Int8: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.UInt8: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.Int16: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.Int32: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.Int64: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.Float32: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + case TypeMarker.Float64: + this.WriteNumber64Value(GetFixedSizedValue(rawValue)); + break; + + case TypeMarker.ArrNumC1: + case TypeMarker.ArrNumC2: + this.WriteRawNumberArray(rawValue, arrayInfo.NestedArrayInfo); + break; + + default: + throw new JsonInvalidTokenException(); + } + } + + private void WriteRawNumberArray( + ReadOnlySpan rawValue, + UniformArrayInfo arrayInfo) + { + if (arrayInfo == null) throw new ArgumentNullException(nameof(arrayInfo)); + + this.WriteArrayStart(); + + int endOffset = arrayInfo.ItemCount * arrayInfo.ItemSize; + switch (arrayInfo.ItemTypeMarker) + { + case TypeMarker.Int8: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.UInt8: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.Int16: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.Int32: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.Int64: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.Float32: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + case TypeMarker.Float64: + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteNumber64Value(GetFixedSizedValue(rawValue.Slice(offset))); + } + break; + + default: + throw new JsonInvalidTokenException(); + } + + this.WriteArrayEnd(); + } + + private void WriteRawNumberArrayArray( + ReadOnlySpan rawValue, + UniformArrayInfo arrayInfo) + { + if (arrayInfo == null) throw new ArgumentNullException(nameof(arrayInfo)); + + this.WriteArrayStart(); + + int endOffset = arrayInfo.ItemCount * arrayInfo.ItemSize; + for (int offset = 0; offset < endOffset; offset += arrayInfo.ItemSize) + { + this.WriteRawNumberArray(rawValue.Slice(offset), arrayInfo.NestedArrayInfo); + } + + this.WriteArrayEnd(); + } + private sealed class ArrayAndObjectInfo { public ArrayAndObjectInfo(long offset, int stringStartIndex, long stringReferenceStartIndex, int valueCount) diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs index 9ea7b42325..9dd28998de 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs @@ -4,7 +4,9 @@ namespace Microsoft.Azure.Cosmos.Json { using System; + using System.Collections.Generic; using System.Globalization; + using System.Linq; using System.Text; using Microsoft.Azure.Cosmos.Core.Utf8; using RMResources = Documents.RMResources; @@ -45,20 +47,20 @@ protected JsonWriter() /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text) /// /// The JsonSerializationFormat of the writer. - /// Initial capacity to help avoid intermeidary allocations. - /// Only applicable to the binary writer + /// The write options the control the write behavior. + /// Initial capacity to help avoid intermediary allocations. /// A JsonWriter that can write in a particular JsonSerializationFormat public static IJsonWriter Create( JsonSerializationFormat jsonSerializationFormat, - int initalCapacity = 256, - bool enableEncodedStrings = true) + JsonWriteOptions writeOptions = JsonWriteOptions.None, + int initialCapacity = 256) { return jsonSerializationFormat switch { - JsonSerializationFormat.Text => new JsonTextWriter(initalCapacity), + JsonSerializationFormat.Text => new JsonTextWriter(initialCapacity), JsonSerializationFormat.Binary => new JsonBinaryWriter( - initialCapacity: initalCapacity, - enableEncodedStrings: enableEncodedStrings), + enableNumberArrays: writeOptions.HasFlag(JsonWriteOptions.EnableNumberArrays), + initialCapacity: initialCapacity), _ => throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, @@ -143,6 +145,104 @@ public virtual void WriteStringValue(string value) /// public abstract void WriteBinaryValue(ReadOnlySpan value); + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (byte value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (sbyte value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (short value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (int value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (long value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (float value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + + /// + public virtual void WriteNumberArray(IReadOnlyList values) + { + this.WriteArrayStart(); + + foreach (double value in values) + { + Number64 number64 = value; + this.WriteNumber64Value(number64); + } + + this.WriteArrayEnd(); + } + /// public abstract ReadOnlyMemory GetResult(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj index 736b507310..b8d65cf141 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj @@ -20,6 +20,7 @@ + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonNavigatorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonNavigatorTests.cs index 265f4b6dce..612b22f388 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonNavigatorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonNavigatorTests.cs @@ -33,7 +33,7 @@ public static void Initialize(TestContext textContext) #region SimpleTests [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrueTest() { string input = "true"; @@ -42,7 +42,7 @@ public void TrueTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void FalseTest() { string input = "false"; @@ -51,7 +51,7 @@ public void FalseTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullTest() { string input = "null"; @@ -60,7 +60,7 @@ public void NullTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntegerTest() { string input = "1337"; @@ -69,7 +69,7 @@ public void IntegerTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DoubleTest() { string input = "1337.0"; @@ -78,7 +78,7 @@ public void DoubleTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NegativeNumberTest() { string input = "-1337.0"; @@ -87,7 +87,7 @@ public void NegativeNumberTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithScientificNotationTest() { string input = "6.02252e23"; @@ -96,7 +96,7 @@ public void NumberWithScientificNotationTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberRegressionTest() { // regression test - the value 0.00085647800000000004 was being incorrectly rejected @@ -106,7 +106,7 @@ public void NumberRegressionTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StringTest() { string input = "\"Hello World\""; @@ -115,7 +115,7 @@ public void StringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyArrayTest() { string input = "[ ] "; @@ -124,7 +124,7 @@ public void EmptyArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntArrayTest() { string input = "[ -2, -1, 0, 1, 2] "; @@ -133,7 +133,7 @@ public void IntArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberArrayTest() { string input = "[15, 22, 0.1, -7.3e-2, 77.0001e90 ] "; @@ -142,7 +142,7 @@ public void NumberArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BooleanArrayTest() { string input = "[ true, false] "; @@ -151,7 +151,7 @@ public void BooleanArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullArrayTest() { string input = "[ null, null, null] "; @@ -160,7 +160,7 @@ public void NullArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ObjectArrayTest() { string input = "[{}, {}] "; @@ -169,7 +169,7 @@ public void ObjectArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitiveArrayTest() { string input = "[0, 0.0, -1, -1.0, 1, 2, \"hello\", null, true, false] "; @@ -178,7 +178,7 @@ public void AllPrimitiveArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NestedArrayTest() { string input = "[[], []] "; @@ -187,7 +187,7 @@ public void NestedArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StrangeNumberArrayTest() { string input = @"[ @@ -201,14 +201,14 @@ public void StrangeNumberArrayTest() { JsonNavigatorTests.VerifyNavigator(input); } - catch (MaterilizationFailedToMatchException) + catch (MaterializationFailedToMatchException) { // Newtonsoft does not use IEEE double precision for these long integers. } } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyObjectTest() { string input = "{}"; @@ -217,7 +217,7 @@ public void EmptyObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SimpleObjectTest() { string input = "{\"GlossDiv\":10,\"title\": \"example glossary\" }"; @@ -226,7 +226,7 @@ public void SimpleObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitivesObjectTest() { string input = @"{ @@ -251,7 +251,7 @@ public void AllPrimitivesObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int8Test() { sbyte[] values = new sbyte[] { sbyte.MinValue, sbyte.MinValue + 1, -1, 0, 1, sbyte.MaxValue, sbyte.MaxValue - 1 }; @@ -263,7 +263,7 @@ public void Int8Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int16Test() { short[] values = new short[] { short.MinValue, short.MinValue + 1, -1, 0, 1, short.MaxValue, short.MaxValue - 1 }; @@ -275,7 +275,7 @@ public void Int16Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int32Test() { int[] values = new int[] { int.MinValue, int.MinValue + 1, -1, 0, 1, int.MaxValue, int.MaxValue - 1 }; @@ -287,7 +287,7 @@ public void Int32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int64Test() { long[] values = new long[] { long.MinValue, long.MinValue + 1, -1, 0, 1, long.MaxValue, long.MaxValue - 1 }; @@ -299,7 +299,7 @@ public void Int64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UInt32Test() { uint[] values = new uint[] { uint.MinValue, uint.MinValue + 1, 0, 1, uint.MaxValue, uint.MaxValue - 1 }; @@ -311,7 +311,7 @@ public void UInt32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float32Test() { float[] values = new float[] { float.MinValue, float.MinValue + 1, 0, 1, float.MaxValue, float.MaxValue - 1 }; @@ -323,7 +323,7 @@ public void Float32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float64Test() { double[] values = new double[] { double.MinValue, double.MinValue + 1, 0, 1, double.MaxValue, double.MaxValue - 1 }; @@ -335,7 +335,7 @@ public void Float64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void GuidTest() { Guid[] values = new Guid[] { Guid.Empty, Guid.NewGuid() }; @@ -347,7 +347,7 @@ public void GuidTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BinaryTest() { { @@ -365,124 +365,123 @@ public void BinaryTest() } #endregion - #region CurratedDocs + #region CuratedDocs [TestMethod] - [Owner("brchon")] - public void CombinedScriptsDataTest() + [Owner("mayapainter")] + public void CuratedDocumentCombinedScriptsDataTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("CombinedScriptsData.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("CombinedScriptsData.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] [Ignore] // This test takes too long - public void CountriesTest() + public void CuratedDocumentCountriesTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("countries", false); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("countries", performExtraChecks: false); } [TestMethod] - [Owner("brchon")] - public void DevTestCollTest() + [Owner("mayapainter")] + public void CuratedDocumentDevTestCollTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("devtestcoll.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("devtestcoll.json"); } [TestMethod] - [Owner("brchon")] - public void LastFMTest() + [Owner("mayapainter")] + public void CuratedDocumentLastFMTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("lastfm"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("lastfm"); } [TestMethod] - [Owner("brchon")] - public void LogDataTest() + [Owner("mayapainter")] + public void CuratedDocumentLogDataTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("LogData.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("LogData.json", performExtraChecks: false); } [TestMethod] - [Owner("brchon")] - public void MillionSong1KDocumentsTest() + [Owner("mayapainter")] + public void CuratedDocumentMillionSong1KDocumentsTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("MillionSong1KDocuments.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("MillionSong1KDocuments.json"); } [TestMethod] - [Owner("brchon")] - public void MsnCollectionTest() + [Owner("mayapainter")] + public void CuratedDocumentMsnCollectionTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("MsnCollection.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("MsnCollection.json"); } [TestMethod] - [Owner("brchon")] - public void NutritionDataTest() + [Owner("mayapainter")] + public void CuratedDocumentNutritionDataTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("NutritionData"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("NutritionData"); } [TestMethod] - [Owner("brchon")] - public void RunsCollectionTest() + [Owner("mayapainter")] + public void CuratedDocumentRunsCollectionTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("runsCollection"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("runsCollection"); } [TestMethod] - [Owner("brchon")] - public void StatesCommitteesTest() + [Owner("mayapainter")] + public void CuratedDocumentStatesCommitteesTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("states_committees.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("states_committees.json"); } [TestMethod] - [Owner("brchon")] - public void StatesLegislatorsTest() + [Owner("mayapainter")] + public void CuratedDocumentStatesLegislatorsTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("states_legislators"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("states_legislators"); } [TestMethod] - [Owner("brchon")] - public void Store01Test() + [Owner("mayapainter")] + public void CuratedDocumentStore01Test() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("store01C.json"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("store01C.json"); } [TestMethod] - [Owner("brchon")] - public void TicinoErrorBucketsTest() + [Owner("mayapainter")] + public void CuratedDocumentTicinoErrorBucketsTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("TicinoErrorBuckets"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("TicinoErrorBuckets"); } [TestMethod] - [Owner("brchon")] - public void TwitterDataTest() + [Owner("mayapainter")] + public void CuratedDocumentTwitterDataTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("twitter_data"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("twitter_data"); } [TestMethod] - [Owner("brchon")] - public void Ups1Test() + [Owner("mayapainter")] + public void CuratedDocumentUps1Test() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("ups1"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("ups1"); } [TestMethod] - [Owner("brchon")] - public void XpertEventsTest() + [Owner("mayapainter")] + public void CuratedDocumentXpertEventsTest() { - JsonNavigatorTests.VerifyNavigatorWithCurratedDoc("XpertEvents"); + JsonNavigatorTests.VerifyNavigatorWithCuratedDoc("XpertEvents"); } - private static void VerifyNavigatorWithCurratedDoc(string path, bool performExtraChecks = true) + private static void VerifyNavigatorWithCuratedDoc(string filename, bool performExtraChecks = true) { - path = string.Format("TestJsons/{0}", path); - string json = TextFileConcatenation.ReadMultipartFile(path); + string json = JsonTestUtils.LoadJsonCuratedDocument(filename); #if true json = JsonTestUtils.RandomSampleJson(json, maxNumberOfItems: 10); #endif @@ -509,8 +508,8 @@ private static void VerifyNavigator( { System.Threading.Thread.CurrentThread.CurrentCulture = cultureInfo; - IJsonReader jsonReader = JsonReader.Create(Encoding.UTF8.GetBytes(input)); - JsonToken[] tokensFromReader = JsonNavigatorTests.GetTokensWithReader(jsonReader); + input = JsonTestUtils.RandomSampleJson(input, maxNumberOfItems: 10); + JsonToken[] tokensFromReader = JsonTestUtils.ReadJsonDocument(input); // Text IJsonNavigator textNavigator = JsonNavigator.Create(Encoding.UTF8.GetBytes(input)); @@ -539,9 +538,17 @@ private static void VerifyNavigator( try { - if (materializedToken.ToString() != JToken.Parse(input).ToString()) + string value1 = materializedToken.ToString(); + string value2 = JToken.Parse(input).ToString(); + if (value1 != value2) { - throw new MaterilizationFailedToMatchException(); + // JToken.Parse might change some values such as Date. + // Before throwing an exception, we first try to apply + // the same Parse to the first value as well. + if (JToken.Parse(value1).ToString() != value2) + { + throw new MaterializationFailedToMatchException(); + } } } catch (Newtonsoft.Json.JsonReaderException) @@ -557,106 +564,10 @@ private static void VerifyNavigator( } } - private static JsonToken[] GetTokensWithReader(IJsonReader jsonReader) - { - List tokens = new List(); - while (jsonReader.Read()) - { - JsonToken token; - switch (jsonReader.CurrentTokenType) - { - case JsonTokenType.NotStarted: - throw new InvalidOperationException(); - - case JsonTokenType.BeginArray: - token = JsonToken.ArrayStart(); - break; - - case JsonTokenType.EndArray: - token = JsonToken.ArrayEnd(); - break; - - case JsonTokenType.BeginObject: - token = JsonToken.ObjectStart(); - break; - - case JsonTokenType.EndObject: - token = JsonToken.ObjectEnd(); - break; - - case JsonTokenType.String: - token = JsonToken.String(jsonReader.GetStringValue()); - break; - - case JsonTokenType.Number: - token = JsonToken.Number(jsonReader.GetNumberValue()); - break; - - case JsonTokenType.True: - token = JsonToken.Boolean(true); - break; - - case JsonTokenType.False: - token = JsonToken.Boolean(false); - break; - - case JsonTokenType.Null: - token = JsonToken.Null(); - break; - - case JsonTokenType.FieldName: - token = JsonToken.FieldName(jsonReader.GetStringValue()); - break; - - case JsonTokenType.Int8: - token = JsonToken.Int8(jsonReader.GetInt8Value()); - break; - - case JsonTokenType.Int16: - token = JsonToken.Int16(jsonReader.GetInt16Value()); - break; - - case JsonTokenType.Int32: - token = JsonToken.Int32(jsonReader.GetInt32Value()); - break; - - case JsonTokenType.Int64: - token = JsonToken.Int64(jsonReader.GetInt64Value()); - break; - - case JsonTokenType.UInt32: - token = JsonToken.UInt32(jsonReader.GetUInt32Value()); - break; - - case JsonTokenType.Float32: - token = JsonToken.Float32(jsonReader.GetFloat32Value()); - break; - - case JsonTokenType.Float64: - token = JsonToken.Float64(jsonReader.GetFloat64Value()); - break; - - case JsonTokenType.Guid: - token = JsonToken.Guid(jsonReader.GetGuidValue()); - break; - - case JsonTokenType.Binary: - token = JsonToken.Binary(jsonReader.GetBinaryValue()); - break; - - default: - throw new ArgumentException($"Unknown {nameof(JsonTokenType)}: {jsonReader.CurrentTokenType}"); - } - - tokens.Add(token); - } - - return tokens.ToArray(); - } - private static JsonToken[] GetTokensFromNode(IJsonNavigatorNode node, IJsonNavigator navigator, bool performCorrectnessCheck) { - switch (navigator.GetNodeType(node)) + JsonNodeType nodeType = navigator.GetNodeType(node); + switch (nodeType) { case JsonNodeType.Null: return new JsonToken[] { JsonToken.Null() }; @@ -775,7 +686,9 @@ private static JsonToken[] GetTokensFromArrayNode(IJsonNavigatorNode node, IJson // Get tokens once again through indexer List tokensFromIndexer = new List(); tokensFromIndexer.Add(JsonToken.ArrayStart()); - for (int i = 0; i < navigator.GetArrayItemCount(node); ++i) + + int itemCount = navigator.GetArrayItemCount(node); + for (int i = 0; i < itemCount; ++i) { tokensFromIndexer.AddRange(JsonNavigatorTests.GetTokensFromNode(navigator.GetArrayItemAt(node, i), navigator, performCorrectnessCheck)); } @@ -784,28 +697,14 @@ private static JsonToken[] GetTokensFromArrayNode(IJsonNavigatorNode node, IJson Assert.AreEqual(arrayItems.Count(), navigator.GetArrayItemCount(node)); Assert.IsTrue(tokensFromIEnumerable.SequenceEqual(tokensFromIndexer)); - - try - { - navigator.GetArrayItemAt(node, navigator.GetArrayItemCount(node) + 1); - Assert.Fail("Expected to get an index out of range exception from going one past the end of the array."); - } - catch (IndexOutOfRangeException) - { - Assert.AreEqual(navigator.SerializationFormat, JsonSerializationFormat.Binary); - } - catch (ArgumentOutOfRangeException) - { - Assert.AreEqual(navigator.SerializationFormat, JsonSerializationFormat.Text); - } } return tokensFromIEnumerable.ToArray(); } - private sealed class MaterilizationFailedToMatchException : Exception + private sealed class MaterializationFailedToMatchException : Exception { - public MaterilizationFailedToMatchException() + public MaterializationFailedToMatchException() { } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs index 2f31613d08..6d3d38a795 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs @@ -39,7 +39,7 @@ public void TestInitialize() #region Literals [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrueTest() { string input = "true"; @@ -59,7 +59,7 @@ public void TrueTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void FalseTest() { string input = "false"; @@ -79,7 +79,7 @@ public void FalseTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullTest() { string input = "null"; @@ -100,7 +100,7 @@ public void NullTest() #endregion #region Numbers [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntegerTest() { string input = "1337"; @@ -122,7 +122,7 @@ public void IntegerTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DoubleTest() { string input = "1337.0"; @@ -144,7 +144,7 @@ public void DoubleTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NegativeNumberTest() { string input = "-1337.0"; @@ -166,7 +166,7 @@ public void NegativeNumberTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithPlusSignTest() { string input = "+1337.0"; @@ -179,7 +179,7 @@ public void NumberWithPlusSignTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithLeadingZeros() { string input = "01"; @@ -204,7 +204,7 @@ public void NumberWithLeadingZeros() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithScientificNotationTest() { string input = "6.02252e23"; @@ -228,7 +228,7 @@ public void NumberWithScientificNotationTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberRegressionTest() { // regression test - the value 0.00085647800000000004 was being incorrectly rejected @@ -252,7 +252,7 @@ public void NumberRegressionTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllNumberRepresentationsTest() { // trying to read 4 from all possible representations @@ -313,7 +313,7 @@ public void AllNumberRepresentationsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberLimitsTest() { // min byte @@ -478,7 +478,7 @@ public void NumberLimitsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberStartingWithDotTest() { string input = ".001"; @@ -491,7 +491,7 @@ public void NumberStartingWithDotTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ScientificWithNoExponent() { string input = "1e"; @@ -506,7 +506,7 @@ public void ScientificWithNoExponent() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ScientificWithPostitiveExponent() { string input = "6.02252e+23"; @@ -522,7 +522,7 @@ public void ScientificWithPostitiveExponent() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ScientificWithNegativeExponent() { string input = "6.02252e-23"; @@ -539,7 +539,7 @@ public void ScientificWithNegativeExponent() #endregion #region Strings [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyStringTest() { string input = "\"\""; @@ -552,7 +552,7 @@ public void EmptyStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StringTest() { string input = "\"Hello World\""; @@ -598,7 +598,7 @@ public void StringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SystemStringTest() { int systemStringId = 0; @@ -622,7 +622,7 @@ public void SystemStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberAsStringTest() { string input = "\"42\""; @@ -635,7 +635,7 @@ public void NumberAsStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BoolAsStringTest() { string input = "\"true\""; @@ -648,7 +648,7 @@ public void BoolAsStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullAsStringTest() { string input = "\"null\""; @@ -661,7 +661,7 @@ public void NullAsStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ArrayAsStringTest() { string input = "\"[]\""; @@ -674,7 +674,7 @@ public void ArrayAsStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ObjectAsStringTest() { string input = "\"{}\""; @@ -687,7 +687,7 @@ public void ObjectAsStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void GuidStringsTest() { { @@ -983,7 +983,7 @@ public void GuidStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DateTimeStringsTest() { { @@ -1184,7 +1184,7 @@ public void DateTimeStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void HexStringsTest() { { @@ -1245,7 +1245,7 @@ public void HexStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EncodedStringLengthTests() { for (int i = JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin; i < JsonBinaryEncoding.TypeMarker.EncodedStringLengthMax; i++) @@ -1270,7 +1270,7 @@ public void EncodedStringLengthTests() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ReferenceStringTests() { string stringPayload = "[\"hello\", \"hello\"]"; @@ -1289,7 +1289,7 @@ public void ReferenceStringTests() byte[] binaryPayload = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, 9, JsonBinaryEncoding.TypeMarker.String1ByteLength, (byte)"hello".Length, @@ -1307,7 +1307,7 @@ public void ReferenceStringTests() byte[] binaryPayload = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, 10, JsonBinaryEncoding.TypeMarker.String1ByteLength, (byte)"hello".Length, @@ -1325,7 +1325,7 @@ public void ReferenceStringTests() byte[] binaryPayload = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, 11, JsonBinaryEncoding.TypeMarker.String1ByteLength, (byte)"hello".Length, @@ -1343,7 +1343,7 @@ public void ReferenceStringTests() byte[] binaryPayload = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, 12, JsonBinaryEncoding.TypeMarker.String1ByteLength, (byte)"hello".Length, @@ -1358,7 +1358,7 @@ public void ReferenceStringTests() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void PackedStringsTest() { { @@ -1514,14 +1514,14 @@ public void PackedStringsTest() #endregion #region Arrays [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ArrayRepresentationTest() { string input = "[true, false]"; byte[] binary1ByteLengthInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, JsonBinaryEncoding.TypeMarker.True, @@ -1531,7 +1531,7 @@ public void ArrayRepresentationTest() byte[] binary1ByteLengthAndCountInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount, + JsonBinaryEncoding.TypeMarker.ArrLC1, // length 2, // count @@ -1543,7 +1543,7 @@ public void ArrayRepresentationTest() byte[] binary2ByteLengthInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array2ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL2, // length 2, 0x00, JsonBinaryEncoding.TypeMarker.True, @@ -1553,7 +1553,7 @@ public void ArrayRepresentationTest() byte[] binary2ByteLengthAndCountInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount, + JsonBinaryEncoding.TypeMarker.ArrLC2, // length 2, 0x00, // count @@ -1565,7 +1565,7 @@ public void ArrayRepresentationTest() byte[] binary4ByteLengthInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array4ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL4, // length 2, 0x00, 0x00, 0x00, JsonBinaryEncoding.TypeMarker.True, @@ -1575,7 +1575,7 @@ public void ArrayRepresentationTest() byte[] binary4ByteLengthAndCountInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount, + JsonBinaryEncoding.TypeMarker.ArrLC4, // length 2, 0x00, 0x00, 0x00, // count @@ -1602,14 +1602,14 @@ public void ArrayRepresentationTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyArrayTest() { string input = "[ ] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.EmptyArray + JsonBinaryEncoding.TypeMarker.Arr0 }; JsonToken[] expectedTokens = @@ -1623,14 +1623,14 @@ public void EmptyArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SingleItemArrayTest() { string input = "[ true ] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.SingleItemArray, + JsonBinaryEncoding.TypeMarker.Arr1, JsonBinaryEncoding.TypeMarker.True }; @@ -1646,13 +1646,13 @@ public void SingleItemArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntArrayTest() { string input = "[ -2, -1, 0, 1, 2] "; List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List numbers = new List @@ -1685,14 +1685,14 @@ public void IntArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberArrayTest() { string input = "[15, 22, 0.1, -7.3e-2, 77.0001e90 ] "; List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List numbers = new List @@ -1725,14 +1725,14 @@ public void NumberArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StringArrayTest() { string input = @"[""Hello"", ""World"", ""Bye""]"; List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List strings = new List @@ -1765,14 +1765,14 @@ public void StringArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BooleanArrayTest() { string input = "[ true, false] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, JsonBinaryEncoding.TypeMarker.True, @@ -1792,14 +1792,14 @@ public void BooleanArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullArrayTest() { string input = "[ null, null, null] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 3, JsonBinaryEncoding.TypeMarker.Null, @@ -1821,18 +1821,18 @@ public void NullArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ObjectArrayTest() { string input = "[{}, {}] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, - JsonBinaryEncoding.TypeMarker.EmptyObject, - JsonBinaryEncoding.TypeMarker.EmptyObject, + JsonBinaryEncoding.TypeMarker.Obj0, + JsonBinaryEncoding.TypeMarker.Obj0, }; JsonToken[] expectedTokens = @@ -1850,13 +1850,13 @@ public void ObjectArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitiveArrayTest() { string input = "[0, 0.0, -1, -1.0, 1, 2, \"hello\", null, true, false] "; List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List elements = new List @@ -1899,18 +1899,18 @@ public void AllPrimitiveArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NestedArrayTest() { string input = "[[], []] "; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, - JsonBinaryEncoding.TypeMarker.EmptyArray, - JsonBinaryEncoding.TypeMarker.EmptyArray, + JsonBinaryEncoding.TypeMarker.Arr0, + JsonBinaryEncoding.TypeMarker.Arr0, }; JsonToken[] expectedTokens = @@ -1928,7 +1928,7 @@ public void NestedArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StrangeNumberArrayTest() { string input = @"[ @@ -1940,7 +1940,7 @@ public void StrangeNumberArrayTest() List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List elements = new List @@ -1971,7 +1971,7 @@ public void StrangeNumberArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ExtendedTypeArrayTest() { string input = @"[I1,H2,L3,LL4,UL5,S6,D7,BbilGgyjThtuSzs5Md/5Dew==,G00000000-0000-0000-0000-000000000000]"; @@ -1979,7 +1979,7 @@ public void ExtendedTypeArrayTest() List bytes = new List { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, JsonBinaryEncoding.TypeMarker.Int8, (byte)1, JsonBinaryEncoding.TypeMarker.Int16 @@ -2023,7 +2023,7 @@ public void ExtendedTypeArrayTest() #endregion #region Escaping [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EscapeCharacterTest() { // Set of all escape characters in JSON. @@ -2053,7 +2053,7 @@ public void EscapeCharacterTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void WhitespaceCharacterTest() { // http://www.ietf.org/rfc/rfc4627.txt for JSON whitespace definition (Section 2). @@ -2074,7 +2074,7 @@ public void WhitespaceCharacterTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnicodeEscapeTest() { { @@ -2109,7 +2109,7 @@ public void UnicodeEscapeTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TwoAdjacentUnicodeCharactersTest() { // 2 unicode escape characters that are not surrogate pairs @@ -2127,7 +2127,7 @@ public void TwoAdjacentUnicodeCharactersTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnicodeTest() { // the user might literally paste a unicode character into the json. @@ -2152,7 +2152,7 @@ public void UnicodeTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmojiUTF32Test() { // the user might literally paste a utf 32 character (like the poop emoji). @@ -2177,7 +2177,7 @@ public void EmojiUTF32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EscapedEmojiUTF32Test() { // the user might want to encode the utf32 character as an escape utf32 character. @@ -2206,7 +2206,7 @@ public void EscapedEmojiUTF32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ControlCharacterTests() { // control characters (U+0000 through U+001F) @@ -2225,14 +2225,14 @@ public void ControlCharacterTests() #endregion #region Objects [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyObjectTest() { string input = "{}"; byte[] binaryInput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.EmptyObject, + JsonBinaryEncoding.TypeMarker.Obj0, }; JsonToken[] expectedTokens = @@ -2246,7 +2246,7 @@ public void EmptyObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SimpleObjectTest() { string input = "{\"GlossDiv\":10,\"title\": \"example glossary\" }"; @@ -2255,7 +2255,7 @@ public void SimpleObjectTest() { List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL1 } }; List elements = new List @@ -2276,7 +2276,7 @@ public void SimpleObjectTest() { List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL1 } }; List elements = new List @@ -2308,7 +2308,7 @@ public void SimpleObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitivesObjectTest() { string input = @"{ @@ -2333,7 +2333,7 @@ public void AllPrimitivesObjectTest() { List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object2ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL2 } }; List elements = new List @@ -2376,11 +2376,11 @@ public void AllPrimitivesObjectTest() }; byte[] innerArrayElementsBytes = innerArrayElements.SelectMany(x => x).ToArray(); - innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Array1ByteLength, (byte)innerArrayElementsBytes.Length }); + innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ArrL1, (byte)innerArrayElementsBytes.Length }); innerObjectElements.Add(innerArrayElementsBytes); byte[] innerObjectElementsBytes = innerObjectElements.SelectMany(x => x).ToArray(); - elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); + elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ObjL1, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "text".Length), 116, 101, 120, 116 }); @@ -2397,7 +2397,7 @@ public void AllPrimitivesObjectTest() { List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object2ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL2 } }; List elements = new List @@ -2440,11 +2440,11 @@ public void AllPrimitivesObjectTest() }; byte[] innerArrayElementsBytes = innerArrayElements.SelectMany(x => x).ToArray(); - innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Array1ByteLength, (byte)innerArrayElementsBytes.Length }); + innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ArrL1, (byte)innerArrayElementsBytes.Length }); innerObjectElements.Add(innerArrayElementsBytes); byte[] innerObjectElementsBytes = innerObjectElements.SelectMany(x => x).ToArray(); - elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); + elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ObjL1, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 7) }); @@ -2504,14 +2504,14 @@ public void AllPrimitivesObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrailingGarbageTest() { string input = "{\"name\":\"477cecf7-5547-4f87-81c2-72ee2c7d6179\",\"permissionMode\":\"Read\",\"resource\":\"-iQET8M3A0c=\"}..garbage.."; List binaryInputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object4ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL4 } }; List elements = new List @@ -2548,7 +2548,7 @@ public void TrailingGarbageTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidIntTest() { string invalidIntString = "{\"type\": 1??? }"; @@ -2564,7 +2564,7 @@ public void InvalidIntTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidExponentTest() { string invalidExponent = "{\"type\": 1.0e-??? }"; @@ -2582,7 +2582,7 @@ public void InvalidExponentTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidExponentTest2() { string invalidExponent = "{\"type\": 1e+1e1 }"; @@ -2600,7 +2600,7 @@ public void InvalidExponentTest2() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidNumberTest() { string input = "{\"type\": 1.e5 }"; @@ -2618,7 +2618,7 @@ public void InvalidNumberTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidNumberWithoutExponentTest() { string input = "{\"type\": 1Garbage }"; @@ -2634,7 +2634,7 @@ public void InvalidNumberWithoutExponentTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingClosingQuoteTest() { string missingQuote = "{\"type\": \"unfinished }"; @@ -2650,7 +2650,7 @@ public void MissingClosingQuoteTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingPropertyTest() { string input = "[{{"; @@ -2666,7 +2666,7 @@ public void MissingPropertyTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingPropertyTest2() { string input = "{true: false}"; @@ -2681,7 +2681,7 @@ public void MissingPropertyTest2() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingNameSeperatorTest() { string input = "{\"prop\"\"value\"}"; @@ -2697,7 +2697,7 @@ public void MissingNameSeperatorTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingValueSeperatorTest() { string input = "[true false]"; @@ -2713,7 +2713,7 @@ public void MissingValueSeperatorTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnexpectedNameSeperatorTest() { string input = "[true: false]"; @@ -2729,7 +2729,7 @@ public void UnexpectedNameSeperatorTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnexpectedEndObjectTest() { string input = "[true,}"; @@ -2745,7 +2745,7 @@ public void UnexpectedEndObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrailingCommaUnexpectedEndObjectTest() { string input = "{\"prop\": false, }"; @@ -2762,7 +2762,7 @@ public void TrailingCommaUnexpectedEndObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnexpectedEndArrayTest() { string input = "{\"prop\": false, ]"; @@ -2779,7 +2779,7 @@ public void UnexpectedEndArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrailingCommaUnexpectedEndArrayTest() { string input = "[true, ]"; @@ -2795,7 +2795,7 @@ public void TrailingCommaUnexpectedEndArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingEndObjectTest() { string input = "{"; @@ -2810,7 +2810,7 @@ public void MissingEndObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingEndArrayTest() { string input = "["; @@ -2825,7 +2825,7 @@ public void MissingEndArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void InvalidEscapeCharacterTest() { JsonToken[] expectedTokens = @@ -2840,7 +2840,7 @@ public void InvalidEscapeCharacterTest() #endregion #region ExtendedTypes [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int8Test() { sbyte[] values = new sbyte[] { sbyte.MinValue, sbyte.MinValue + 1, -1, 0, 1, sbyte.MaxValue, sbyte.MaxValue - 1 }; @@ -2869,7 +2869,7 @@ public void Int8Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int16Test() { short[] values = new short[] { short.MinValue, short.MinValue + 1, -1, 0, 1, short.MaxValue, short.MaxValue - 1 }; @@ -2898,7 +2898,7 @@ public void Int16Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int32Test() { int[] values = new int[] { int.MinValue, int.MinValue + 1, -1, 0, 1, int.MaxValue, int.MaxValue - 1 }; @@ -2927,7 +2927,7 @@ public void Int32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int64Test() { long[] values = new long[] { long.MinValue, long.MinValue + 1, -1, 0, 1, long.MaxValue, long.MaxValue - 1 }; @@ -2956,7 +2956,7 @@ public void Int64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UInt32Test() { uint[] values = new uint[] { uint.MinValue, uint.MinValue + 1, 0, 1, uint.MaxValue, uint.MaxValue - 1 }; @@ -2985,7 +2985,7 @@ public void UInt32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float32Test() { float[] values = new float[] { float.MinValue, float.MinValue + 1, 0, 1, float.MaxValue, float.MaxValue - 1 }; @@ -3014,7 +3014,7 @@ public void Float32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float64Test() { double[] values = new double[] { double.MinValue, double.MinValue + 1, 0, 1, double.MaxValue, double.MaxValue - 1 }; @@ -3043,7 +3043,7 @@ public void Float64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void GuidTest() { Guid[] values = new Guid[] { Guid.Empty, Guid.NewGuid() }; @@ -3072,7 +3072,7 @@ public void GuidTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BinaryTest() { { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonRoundtripTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonRoundtripTests.cs index f58dcefc0f..2a4841cd3a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonRoundtripTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonRoundtripTests.cs @@ -6,176 +6,280 @@ namespace Microsoft.Azure.Cosmos.Tests.Json { using System; - using System.Collections.Generic; + using System.Collections; + using System.Diagnostics; using System.Text; - using Microsoft.Azure.Cosmos.Core.Utf8; using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Cosmos.Json.Interop; - using Microsoft.Azure.Cosmos.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; + using static Microsoft.Azure.Cosmos.Tests.Json.JsonTestUtils; [TestClass] public class JsonRoundTripsTests { #region Literals [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrueTest() { string input = "true"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void FalseTest() { string input = "false"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullTest() { string input = "null"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } #endregion + #region Numbers [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntegerTest() { string input = "1337"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DoubleTest() { string input = "1337.7"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NegativeNumberTest() { string input = "-1337.7"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithScientificNotationTest() { string input = "6.02252E+23"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ScientificWithPostitiveExponent() { string input = "6.02252E+23"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ScientificWithNegativeExponent() { string input = "6.02252E-23"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } #endregion + #region Strings [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyStringTest() { string input = "\"\""; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StringTest() { string input = "\"Hello World\""; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } #endregion + #region Arrays [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyArrayTest() { string input = "[ ] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] - public void IntArrayTest() + [Owner("mayapainter")] + public void UniformNumberArrayTest1() { + // Int8 string input = "[ -2, -1, 0, 1, 2] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformNumberArrayTest2() + { + // UInt8 + string input = "[ 15, 0, 4, 25, 100] "; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformNumberArrayTest3() + { + // Int16 + string input = "[ 300, -1251, 8944, -1024 ] "; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformNumberArrayTest4() + { + // Int32 + string input = "[ 77111, 187345, -1, 0, 255 ] "; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformNumberArrayTest5() + { + // Int64 + string input = "[ -128, 8589934592, -8, 4, 127 ] "; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformNumberArrayTest6() + { + // Float64 + string input = "[ -1.1, 1.1, 0, 4, 1.5 ] "; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest1() + { + // Int8 + string input = "[ [1, -2], [-1, 2], [-1, -2] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest2() + { + // UInt8 + string input = "[ [40, 50, 60], [50, 60, 70], [60, 70, 80] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest3() + { + // Int16 + string input = "[ [400, 500, 600, 700], [-400, -500, -600, -700] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest4() + { + // Int32 + string input = "[ [222000, 333000, 444000, 555000], [222000, 333000, 444000, 555000] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest5() + { + // Int64 + string input = "[ [222000222000, 333000333000, 444000444000, 555000555000], [222000222000, 333000333000, 444000444000, 555000555000] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); + } + + [TestMethod] + [Owner("mayapainter")] + public void UniformArrayOfNumberArrayTest6() + { + // Float64 + string input = "[ [2.1, 1.1, 0.1, -0.1, -1.1, -2.1], [1.1, 1.2, 1.3, 1.4, 1.5, 1.6], [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] ]"; + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberArrayTest() { string input = "[15, 22, 0.1] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BooleanArrayTest() { string input = "[ true, false] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullArrayTest() { string input = "[ null, null, null] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ObjectArrayTest() { string input = "[{}, {}] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitiveArrayTest() { string input = "[0, 0.1, -1, -1.1, 1, 2, \"hello\", null, true, false] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NestedArrayTest() { string input = "[[], []] "; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } #endregion + #region Escaping [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EscapeCharacterTest() { /// @@ -196,56 +300,57 @@ public void EscapeCharacterTest() foreach (Tuple escapeCharacter in escapeCharacters) { string input = "\"" + escapeCharacter.Item1 + "\""; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void WhitespaceCharacterTest() { string input = "[" + " " + "\"hello\"" + "," + "\t" + "\"my\"" + "\r" + "," + "\"name\"" + "\n" + "," + "\"is\"" + "]"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnicodeTest() { // the user might literally paste a unicode character into the json. string unicodeString = "\"€\""; - JsonRoundTripsTests.PerformRoundTripTest(unicodeString); + JsonRoundTripsTests.VerifyRoundTripTest(unicodeString); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmojiUTF32Test() { // the user might literally paste a utf 32 character (like the poop emoji). string unicodeString = "\"💩\""; - JsonRoundTripsTests.PerformRoundTripTest(unicodeString); + JsonRoundTripsTests.VerifyRoundTripTest(unicodeString); } #endregion + #region Objects [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyObjectTest() { string input = "{}"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SimpleObjectTest() { string input = "{\"GlossDiv\":10,\"title\": \"example glossary\" }"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitivesObjectTest() { string input = @"{ @@ -265,133 +370,134 @@ public void AllPrimitivesObjectTest() }, ""text"": ""tiger diamond newbrunswick snowleopard chocolate dog snowleopard turtle cat sapphire peach sapphire vancouver white chocolate horse diamond lion superlongcolourname ruby"" }"; - JsonRoundTripsTests.PerformRoundTripTest(input); + JsonRoundTripsTests.VerifyRoundTripTest(input); } #endregion + #region Limits [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberLimitsTest() { // min byte string minByteInput = "0"; - JsonRoundTripsTests.PerformRoundTripTest(minByteInput); + JsonRoundTripsTests.VerifyRoundTripTest(minByteInput); // max byte string maxByteInput = "255"; - JsonRoundTripsTests.PerformRoundTripTest(maxByteInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxByteInput); // min short string minShortInput = "-32768"; - JsonRoundTripsTests.PerformRoundTripTest(minShortInput); + JsonRoundTripsTests.VerifyRoundTripTest(minShortInput); // max short string maxShortInput = "32767"; - JsonRoundTripsTests.PerformRoundTripTest(maxShortInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxShortInput); // min int string minIntInput = "-2147483648"; - JsonRoundTripsTests.PerformRoundTripTest(minIntInput); + JsonRoundTripsTests.VerifyRoundTripTest(minIntInput); // max int string maxIntInput = "2147483647"; - JsonRoundTripsTests.PerformRoundTripTest(maxIntInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxIntInput); // min long string minLongInput = "-9223372036854775808"; - JsonRoundTripsTests.PerformRoundTripTest(minLongInput); + JsonRoundTripsTests.VerifyRoundTripTest(minLongInput); // max long string maxLongInput = "9223372036854775807"; - JsonRoundTripsTests.PerformRoundTripTest(maxLongInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxLongInput); // min double string minDoubleInput = "-1.7976931348623157E+308"; - JsonRoundTripsTests.PerformRoundTripTest(minDoubleInput); + JsonRoundTripsTests.VerifyRoundTripTest(minDoubleInput); // max double string maxDoubleInput = "1.7976931348623157E+308"; - JsonRoundTripsTests.PerformRoundTripTest(maxDoubleInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxDoubleInput); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ArrayLengthLimitsTest() { // empty array string emptyArrayInput = "[]"; - JsonRoundTripsTests.PerformRoundTripTest(emptyArrayInput); + JsonRoundTripsTests.VerifyRoundTripTest(emptyArrayInput); // single item array string singleItemArrayInput = @"[""a""]"; - JsonRoundTripsTests.PerformRoundTripTest(singleItemArrayInput); + JsonRoundTripsTests.VerifyRoundTripTest(singleItemArrayInput); // max 1 byte length array string maxByteLengthPayload = new string('a', byte.MaxValue - 1 - 1); string maxByteLengthInput = @"[""" + maxByteLengthPayload + @"""]"; - JsonRoundTripsTests.PerformRoundTripTest(maxByteLengthInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxByteLengthInput); // max 2 byte length array string maxUShortLengthPayload = new string('a', ushort.MaxValue - 1 - 2); string maxUShortLengthInput = @"[""" + maxUShortLengthPayload + @"""]"; - JsonRoundTripsTests.PerformRoundTripTest(maxUShortLengthInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxUShortLengthInput); // max 4 byte length array string maxUIntLengthPayload = new string('a', ushort.MaxValue); string maxUIntLengthInput = @"[""" + maxUIntLengthPayload + @"""]"; - JsonRoundTripsTests.PerformRoundTripTest(maxUIntLengthInput); + JsonRoundTripsTests.VerifyRoundTripTest(maxUIntLengthInput); } #endregion - #region CuratedDocuments + #region CuratedDocuments [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void CombinedScriptsDataTest() { - this.RoundTripTestCuratedJson("CombinedScriptsData.json"); + this.VerifyCuratedJsonRoundTripTest("CombinedScriptsData.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] [Ignore] // Takes too long public void CountriesTest() { - this.RoundTripTestCuratedJson("countries"); + this.VerifyCuratedJsonRoundTripTest("countries"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DevTestCollTest() { - this.RoundTripTestCuratedJson("devtestcoll.json"); + this.VerifyCuratedJsonRoundTripTest("devtestcoll.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void LastFMTest() { - this.RoundTripTestCuratedJson("lastfm"); + this.VerifyCuratedJsonRoundTripTest("lastfm"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void LogDataTest() { - this.RoundTripTestCuratedJson("LogData.json"); + this.VerifyCuratedJsonRoundTripTest("LogData.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MillionSong1KDocumentsTest() { - this.RoundTripTestCuratedJson("MillionSong1KDocuments.json"); + this.VerifyCuratedJsonRoundTripTest("MillionSong1KDocuments.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MsnCollectionTest() { - this.RoundTripTestCuratedJson("MsnCollection.json"); + this.VerifyCuratedJsonRoundTripTest("MsnCollection.json"); } [TestMethod] @@ -422,212 +528,181 @@ public void LargeArrayBinaryJsonTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NutritionDataTest() { - this.RoundTripTestCuratedJson("NutritionData"); + this.VerifyCuratedJsonRoundTripTest("NutritionData"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void RunsCollectionTest() { - this.RoundTripTestCuratedJson("runsCollection"); + this.VerifyCuratedJsonRoundTripTest("runsCollection"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StatesCommitteesTest() { - this.RoundTripTestCuratedJson("states_committees.json"); + this.VerifyCuratedJsonRoundTripTest("states_committees.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StatesLegislatorsTest() { - this.RoundTripTestCuratedJson("states_legislators"); + this.VerifyCuratedJsonRoundTripTest("states_legislators"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Store01Test() { - this.RoundTripTestCuratedJson("store01C.json"); + this.VerifyCuratedJsonRoundTripTest("store01C.json"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TicinoErrorBucketsTest() { - this.RoundTripTestCuratedJson("TicinoErrorBuckets"); + this.VerifyCuratedJsonRoundTripTest("TicinoErrorBuckets"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TwitterDataTest() { - this.RoundTripTestCuratedJson("twitter_data"); + this.VerifyCuratedJsonRoundTripTest("twitter_data"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Ups1Test() { - this.RoundTripTestCuratedJson("ups1"); + this.VerifyCuratedJsonRoundTripTest("ups1"); } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void XpertEventsTest() { - this.RoundTripTestCuratedJson("XpertEvents"); + this.VerifyCuratedJsonRoundTripTest("XpertEvents"); } + #endregion - // Checks to see if we can go from a JsonReader to a NewtonsoftWriter and get back the original document and visa versa - private void RoundTripTestCuratedJson(string path) + private static void VerifyRoundTripTest(string inputJson) { - path = string.Format("TestJsons/{0}", path); - string json = TextFileConcatenation.ReadMultipartFile(path); -#if true - json = JsonTestUtils.RandomSampleJson(json, seed: 42, maxNumberOfItems: 100); -#endif - JsonRoundTripsTests.MultiSerializationRoundTrip(json); + // Do the actual roundtrips + JsonToken[] inputTokens = JsonTestUtils.ReadJsonDocument(inputJson); + JsonRoundTripsTests.MultiSerializationRoundTrip(inputTokens, inputJson); } - #endregion - private enum SerializationFormat + // Checks to see if we can go from a JsonReader to a NewtonsoftWriter and get back the original document and visa versa + private void VerifyCuratedJsonRoundTripTest(string filename, int maxNumberOfItems = 100) { - Text, - Binary, - NewtonsoftText, - //BinaryWithDictionaryEncoding, + string inputJson = JsonTestUtils.LoadJsonCuratedDocument(filename); + inputJson = JsonTestUtils.RandomSampleJson(inputJson, maxNumberOfItems, seed: 42); + JsonToken[] inputTokens = JsonTestUtils.ReadJsonDocument(inputJson); + MultiSerializationRoundTrip(inputTokens, inputJson); } - private static void MultiSerializationRoundTrip(string json) + private static void MultiSerializationRoundTrip(JsonToken[] inputTokens, string inputJson) { - foreach (SerializationFormat sourceFormat in Enum.GetValues(typeof(SerializationFormat))) { - foreach (SerializationFormat destinationFormat in Enum.GetValues(typeof(SerializationFormat))) + // Verify native Cosmos formats and write options round-trips + JsonTestUtils.SerializationSpec[] serializationSpecs = { - foreach (bool writeAsRootNode in new bool[] { true, false }) - { - PerformRoundTrip(sourceFormat, destinationFormat, json, writeAsRootNode); - } - } - } - } + SerializationSpec.Text(JsonWriteOptions.None), + SerializationSpec.Binary(JsonWriteOptions.None), + SerializationSpec.Binary(JsonWriteOptions.EnableNumberArrays), + }; - private static void PerformRoundTrip( - SerializationFormat sourceFormat, - SerializationFormat destinationFormat, - string json, - bool writeAsRootNode) - { - IJsonReader reader = sourceFormat switch - { - SerializationFormat.Text => JsonReader.Create(Encoding.UTF8.GetBytes(json)), - SerializationFormat.Binary => JsonReader.Create(JsonTestUtils.ConvertTextToBinary(json)), - SerializationFormat.NewtonsoftText => NewtonsoftToCosmosDBReader.CreateFromString(json), - _ => throw new ArgumentException($"Unexpected {nameof(sourceFormat)} of type: {sourceFormat}"), - }; + RewriteScenario[] rewriteScenarios = + { + RewriteScenario.NavigatorRoot, + RewriteScenario.NavigatorNode, + RewriteScenario.ReaderAll, + RewriteScenario.ReaderToken, + }; - IJsonNavigator navigator = sourceFormat switch - { - SerializationFormat.Text => JsonNavigator.Create(Encoding.UTF8.GetBytes(json)), - SerializationFormat.Binary => JsonNavigator.Create(JsonTestUtils.ConvertTextToBinary(json)), - SerializationFormat.NewtonsoftText => new JsonNewtonsoftNavigator(json), - _ => throw new ArgumentException($"Unexpected {nameof(sourceFormat)} of type: {sourceFormat}"), - }; + MultiSerializationRoundTrip(inputTokens, inputJson, serializationSpecs, rewriteScenarios); + } - foreach (object source in new object[] { reader, navigator }) { - IJsonWriter writer = destinationFormat switch + // Verify Text to Newtonsoft round-trip + SerializationSpec[] serializationSpecs = { - SerializationFormat.Text => JsonWriter.Create(JsonSerializationFormat.Text), - SerializationFormat.Binary => JsonWriter.Create(JsonSerializationFormat.Binary), - SerializationFormat.NewtonsoftText => NewtonsoftToCosmosDBWriter.CreateTextWriter(), - _ => throw new ArgumentException($"Unexpected {nameof(destinationFormat)} of type: {destinationFormat}"), + SerializationSpec.Text(JsonWriteOptions.None), + SerializationSpec.Newtonsoft(), }; - switch (source) - { - case IJsonReader sourceReader: - sourceReader.WriteAll(writer); - break; - - case IJsonNavigator sourceNavigator: - if (writeAsRootNode) - { - sourceNavigator.WriteNode(sourceNavigator.GetRootNode(), writer); - } - else - { - IJsonNavigatorNode rootNode = sourceNavigator.GetRootNode(); - JsonNodeType jsonNodeType = sourceNavigator.GetNodeType(rootNode); - switch (jsonNodeType) - { - case JsonNodeType.Array: - writer.WriteArrayStart(); - - foreach (IJsonNavigatorNode arrayItem in sourceNavigator.GetArrayItems(rootNode)) - { - sourceNavigator.WriteNode(arrayItem, writer); - } - - writer.WriteArrayEnd(); - break; - - case JsonNodeType.Object: - writer.WriteObjectStart(); - - foreach (ObjectProperty objectProperty in sourceNavigator.GetObjectProperties(rootNode)) - { - sourceNavigator.WriteNode(objectProperty.NameNode, writer); - sourceNavigator.WriteNode(objectProperty.ValueNode, writer); - } - - writer.WriteObjectEnd(); - break; - - default: - sourceNavigator.WriteNode(sourceNavigator.GetRootNode(), writer); - break; - } - } - break; - - default: - Assert.Fail("Failed to downcast source type."); - break; - } - - string result = writer.SerializationFormat switch + RewriteScenario[] rewriteScenarios = { - JsonSerializationFormat.Text => Utf8String.UnsafeFromUtf8BytesNoValidation(writer.GetResult()).ToString(), - JsonSerializationFormat.Binary => JsonTestUtils.ConvertBinaryToText(writer.GetResult()), - _ => throw new ArgumentException(), + RewriteScenario.NavigatorNode, + RewriteScenario.ReaderToken, }; - string normalizedResult = JsonRoundTripsTests.NewtonsoftFormat(result); - string normalizedJson = JsonRoundTripsTests.NewtonsoftFormat(json); - Assert.AreEqual(normalizedJson, normalizedResult); + MultiSerializationRoundTrip(inputTokens, inputJson, serializationSpecs, rewriteScenarios); } } - - private static string NewtonsoftFormat(string json) + private static void MultiSerializationRoundTrip( + JsonToken[] inputTokens, + string inputJson, + SerializationSpec[] serializationSpecs, + RewriteScenario[] rewriteScenarios) { - NewtonsoftToCosmosDBReader newtonsoftReader = NewtonsoftToCosmosDBReader.CreateFromString(json); - NewtonsoftToCosmosDBWriter newtonsoftWriter = NewtonsoftToCosmosDBWriter.CreateTextWriter(); - newtonsoftReader.WriteAll(newtonsoftWriter); - return Encoding.UTF8.GetString(newtonsoftWriter.GetResult().ToArray()); - } + Console.WriteLine(); + Console.WriteLine($"Input JSON Length: {inputJson.Length}"); + Console.WriteLine($"Input Token Count: {inputTokens.Length}"); - private static void PerformRoundTripTest(string input) - { - // Do the actual roundtrips - JsonRoundTripsTests.MultiSerializationRoundTrip(input); + ReadOnlyMemory[] expectedOutputResults = new ReadOnlyMemory[serializationSpecs.Length]; + + foreach (SerializationSpec inputSpec in serializationSpecs) + { + Stopwatch timer = Stopwatch.StartNew(); + + IJsonWriter inputWriter = inputSpec.IsNewtonsoft ? + NewtonsoftToCosmosDBWriter.CreateTextWriter() : + JsonWriter.Create(inputSpec.SerializationFormat, inputSpec.WriteOptions); + + JsonTestUtils.WriteTokens(inputTokens, inputWriter, writeAsUtf8String: true); + ReadOnlyMemory inputResult = inputWriter.GetResult(); + + timer.Stop(); + + Console.WriteLine(); + Console.WriteLine($" -- Input Format '{inputSpec.SerializationFormatToString()}'"); + Console.WriteLine($" Input Write Time (ms): {timer.ElapsedMilliseconds}"); + Console.WriteLine($" Input Result Length : {inputResult.Length}"); + + for (int i = 0; i < serializationSpecs.Length; i++) + { + SerializationSpec outputSpec = serializationSpecs[i]; + + Console.WriteLine($" -- Output Format '{outputSpec.SerializationFormatToString()}'"); + + RoundTripResult roundTripResult = null; + foreach (RewriteScenario scenario in rewriteScenarios) + { + roundTripResult = VerifyJsonRoundTrip( + inputResult, + inputJson, + inputSpec, + outputSpec, + scenario, + expectedOutputResults[i], + (string _) => new JsonNewtonsoftNavigator(_)); + + expectedOutputResults[i] = roundTripResult.OutputResult; + + Console.WriteLine($" Scenario '{scenario}'"); + Console.WriteLine($" Execution Time (ms): {roundTripResult.ExecutionTime,5}"); + Console.WriteLine($" Verification Time (ms): {roundTripResult.VerificationTime,5}"); + } + } + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTestUtils.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTestUtils.cs index 22a5d8bf97..3d1a09e805 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTestUtils.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTestUtils.cs @@ -2,11 +2,18 @@ { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Utf8; + using Microsoft.Azure.Cosmos.Json.Interop; using Microsoft.Azure.Cosmos.Json; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Microsoft.Azure.Cosmos.Core; + using System.Diagnostics; - internal static class JsonTestUtils + internal class JsonTestUtils { public static byte[] ConvertTextToBinary(string text) { @@ -24,50 +31,855 @@ public static string ConvertBinaryToText(ReadOnlyMemory binary) return Encoding.UTF8.GetString(textWriter.GetResult().ToArray()); } - public static string RandomSampleJson( - string json, - int? seed = null, - int maxNumberOfItems = 10) + public static string LoadJsonCuratedDocument(string filename) { - Newtonsoft.Json.Linq.JToken root = (Newtonsoft.Json.Linq.JToken)Newtonsoft.Json.JsonConvert.DeserializeObject(json); - Random random = seed.HasValue ? new Random(seed.Value) : new Random(); + string path = string.Format("TestJsons/{0}", filename); + return TextFileConcatenation.ReadMultipartFile(path); + } + public static string RandomSampleJson( + string inputJson, + int maxNumberOfItems, + int? seed = null) + { string sampledJson; - if(root.Type == Newtonsoft.Json.Linq.JTokenType.Array) + + IJsonNavigator navigator = JsonNavigator.Create(Encoding.UTF8.GetBytes(inputJson)); + + IJsonNavigatorNode rootNode = navigator.GetRootNode(); + JsonNodeType rootNodeType = navigator.GetNodeType(rootNode); + if (rootNodeType == JsonNodeType.Array) + { + if (navigator.GetArrayItemCount(rootNode) > maxNumberOfItems) + { + Random random = seed.HasValue ? new Random(seed.Value) : new Random(); + + IJsonNavigatorNode[] arrayItems = navigator.GetArrayItems(rootNode).ToArray(); + IJsonNavigatorNode[] randomArrayItems = new IJsonNavigatorNode[maxNumberOfItems]; + + HashSet uniqueIndexes = new HashSet(); + + int count = 0; + while (count < maxNumberOfItems) + { + int index = random.Next(arrayItems.Length); + if (!uniqueIndexes.Contains(index)) + { + randomArrayItems[count++] = arrayItems[index]; + uniqueIndexes.Add(index); + } + } + + IJsonWriter writer = JsonWriter.Create(JsonSerializationFormat.Text); + + writer.WriteArrayStart(); + foreach (IJsonNavigatorNode item in randomArrayItems) + { + navigator.WriteNode(item, writer); + } + writer.WriteArrayEnd(); + + sampledJson = Encoding.UTF8.GetString(writer.GetResult().ToArray()); + } + else + { + sampledJson = inputJson; + } + } + else + { + sampledJson = inputJson; + } + + return sampledJson; + } + + public static JsonToken[] ReadJsonDocument(string inputJson) + { + IJsonReader reader = JsonReader.Create(Encoding.UTF8.GetBytes(inputJson)); + return ReadJsonDocument(reader); + } + + public static JsonToken[] ReadJsonDocument(IJsonReader reader) + { + List tokens = new List(); + while (reader.Read()) { - Newtonsoft.Json.Linq.JArray array = (Newtonsoft.Json.Linq.JArray)root; - IEnumerable tokens = array - .OrderBy(x => random.Next()) - .Take(random.Next(maxNumberOfItems)); - Newtonsoft.Json.Linq.JArray newArray = new Newtonsoft.Json.Linq.JArray(); - foreach (Newtonsoft.Json.Linq.JToken token in tokens) + JsonToken token; + switch (reader.CurrentTokenType) { - newArray.Add(token); + case JsonTokenType.NotStarted: + throw new InvalidOperationException(); + + case JsonTokenType.BeginArray: + token = JsonToken.ArrayStart(); + break; + + case JsonTokenType.EndArray: + token = JsonToken.ArrayEnd(); + break; + + case JsonTokenType.BeginObject: + token = JsonToken.ObjectStart(); + break; + + case JsonTokenType.EndObject: + token = JsonToken.ObjectEnd(); + break; + + case JsonTokenType.String: + token = JsonToken.String(reader.GetStringValue()); + break; + + case JsonTokenType.Number: + token = JsonToken.Number(reader.GetNumberValue()); + break; + + case JsonTokenType.True: + token = JsonToken.Boolean(true); + break; + + case JsonTokenType.False: + token = JsonToken.Boolean(false); + break; + + case JsonTokenType.Null: + token = JsonToken.Null(); + break; + + case JsonTokenType.FieldName: + token = JsonToken.FieldName(reader.GetStringValue()); + break; + + case JsonTokenType.Int8: + token = JsonToken.Int8(reader.GetInt8Value()); + break; + + case JsonTokenType.Int16: + token = JsonToken.Int16(reader.GetInt16Value()); + break; + + case JsonTokenType.Int32: + token = JsonToken.Int32(reader.GetInt32Value()); + break; + + case JsonTokenType.Int64: + token = JsonToken.Int64(reader.GetInt64Value()); + break; + + case JsonTokenType.UInt32: + token = JsonToken.UInt32(reader.GetUInt32Value()); + break; + + case JsonTokenType.Float32: + token = JsonToken.Float32(reader.GetFloat32Value()); + break; + + case JsonTokenType.Float64: + token = JsonToken.Float64(reader.GetFloat64Value()); + break; + + case JsonTokenType.Guid: + token = JsonToken.Guid(reader.GetGuidValue()); + break; + + case JsonTokenType.Binary: + token = JsonToken.Binary(reader.GetBinaryValue()); + break; + + default: + throw new ArgumentException($"Unknown {nameof(JsonTokenType)}: {reader.CurrentTokenType}"); } - sampledJson = newArray.ToString(); + tokens.Add(token); } - else if(root.Type == Newtonsoft.Json.Linq.JTokenType.Object) + + return tokens.ToArray(); + } + + public static void WriteTokens( + JsonToken[] tokensToWrite, + IJsonWriter jsonWriter, + bool writeAsUtf8String) + { + Assert.IsNotNull(tokensToWrite); + Assert.IsNotNull(jsonWriter); + + foreach (JsonToken token in tokensToWrite) { - Newtonsoft.Json.Linq.JObject jobject = (Newtonsoft.Json.Linq.JObject)root; - IEnumerable properties = jobject - .Properties() - .OrderBy(x => random.Next()) - .Take(maxNumberOfItems); - Newtonsoft.Json.Linq.JObject newObject = new Newtonsoft.Json.Linq.JObject(); - foreach(Newtonsoft.Json.Linq.JProperty property in properties) + if (token.IsNumberArray) { - newObject.Add(property); + switch (token.JsonTokenType) + { + case JsonTokenType.UInt8: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Int8: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Int16: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Int32: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Int64: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Float32: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + + case JsonTokenType.Float64: + jsonWriter.WriteNumberArray((token as JsonNumberArrayToken).Values); + break; + default: + Assert.Fail($"Unexpected number array JsonTokenType: {token.JsonTokenType}."); + break; + } } + else + { + switch (token.JsonTokenType) + { + case JsonTokenType.BeginArray: + jsonWriter.WriteArrayStart(); + break; + + case JsonTokenType.EndArray: + jsonWriter.WriteArrayEnd(); + break; + + case JsonTokenType.BeginObject: + jsonWriter.WriteObjectStart(); + break; + + case JsonTokenType.EndObject: + jsonWriter.WriteObjectEnd(); + break; + + case JsonTokenType.String: + string stringValue = (token as JsonStringToken).Value; + if (writeAsUtf8String) + { + jsonWriter.WriteStringValue(Utf8Span.TranscodeUtf16(stringValue)); + } + else + { + jsonWriter.WriteStringValue(stringValue); + } + break; + + case JsonTokenType.Number: + Number64 numberValue = (token as JsonNumberToken).Value; + jsonWriter.WriteNumber64Value(numberValue); + break; + + case JsonTokenType.True: + jsonWriter.WriteBoolValue(true); + break; + + case JsonTokenType.False: + jsonWriter.WriteBoolValue(false); + break; + + case JsonTokenType.Null: + jsonWriter.WriteNullValue(); + break; + + case JsonTokenType.FieldName: + string fieldNameValue = (token as JsonFieldNameToken).Value; + if (writeAsUtf8String) + { + jsonWriter.WriteFieldName(Utf8Span.TranscodeUtf16(fieldNameValue)); + } + else + { + jsonWriter.WriteFieldName(fieldNameValue); + } + break; + + case JsonTokenType.Int8: + sbyte int8Value = (token as JsonInt8Token).Value; + jsonWriter.WriteInt8Value(int8Value); + break; + + case JsonTokenType.Int16: + short int16Value = (token as JsonInt16Token).Value; + jsonWriter.WriteInt16Value(int16Value); + break; + + case JsonTokenType.Int32: + int int32Value = (token as JsonInt32Token).Value; + jsonWriter.WriteInt32Value(int32Value); + break; + + case JsonTokenType.Int64: + long int64Value = (token as JsonInt64Token).Value; + jsonWriter.WriteInt64Value(int64Value); + break; + + case JsonTokenType.UInt32: + uint uint32Value = (token as JsonUInt32Token).Value; + jsonWriter.WriteUInt32Value(uint32Value); + break; + + case JsonTokenType.Float32: + float float32Value = (token as JsonFloat32Token).Value; + jsonWriter.WriteFloat32Value(float32Value); + break; + + case JsonTokenType.Float64: + double float64Value = (token as JsonFloat64Token).Value; + jsonWriter.WriteFloat64Value(float64Value); + break; + + case JsonTokenType.Guid: + Guid guidValue = (token as JsonGuidToken).Value; + jsonWriter.WriteGuidValue(guidValue); + break; - sampledJson = newObject.ToString(); + case JsonTokenType.Binary: + ReadOnlyMemory binaryValue = (token as JsonBinaryToken).Value; + jsonWriter.WriteBinaryValue(binaryValue.Span); + break; + + case JsonTokenType.NotStarted: + default: + Assert.Fail(string.Format("Got an unexpected JsonTokenType: {0} as an expected token type", token.JsonTokenType)); + break; + } + } } - else + } + + public static RoundTripResult VerifyJsonRoundTrip( + ReadOnlyMemory inputResult, + string inputJson, + SerializationSpec inputSpec, + SerializationSpec outputSpec, + RewriteScenario rewriteScenario, + ReadOnlyMemory expectedOutputResult = default, + Func newtonsoftNavigatorCreate = default) + { + Func createReader = (SerializationSpec spec) => spec.IsNewtonsoft ? + NewtonsoftToCosmosDBReader.CreateFromString(inputJson) : + JsonReader.Create(inputResult); + + Func createNavigator = (SerializationSpec spec) => spec.IsNewtonsoft ? + (newtonsoftNavigatorCreate != null ? newtonsoftNavigatorCreate(inputJson) : null) : + JsonNavigator.Create(inputResult); + + Func createWriter = (SerializationSpec spec) => spec.IsNewtonsoft ? + NewtonsoftToCosmosDBWriter.CreateTextWriter() : + JsonWriter.Create(spec.SerializationFormat, spec.WriteOptions); + + Stopwatch timer = Stopwatch.StartNew(); + + IJsonWriter outputWriter = createWriter(outputSpec); + switch (rewriteScenario) { - sampledJson = json; + case RewriteScenario.NavigatorRoot: + { + IJsonNavigator inputNavigator = createNavigator(inputSpec); + inputNavigator.WriteNode(inputNavigator.GetRootNode(), outputWriter); + } + break; + + case RewriteScenario.NavigatorNode: + { + IJsonNavigator inputNavigator = createNavigator(inputSpec); + IJsonNavigatorNode rootNode = inputNavigator.GetRootNode(); + JsonNodeType nodeType = inputNavigator.GetNodeType(rootNode); + switch (nodeType) + { + case JsonNodeType.Array: + outputWriter.WriteArrayStart(); + + foreach (IJsonNavigatorNode arrayItem in inputNavigator.GetArrayItems(rootNode)) + { + inputNavigator.WriteNode(arrayItem, outputWriter); + } + + outputWriter.WriteArrayEnd(); + break; + + case JsonNodeType.Object: + outputWriter.WriteObjectStart(); + + foreach (ObjectProperty objectProperty in inputNavigator.GetObjectProperties(rootNode)) + { + inputNavigator.WriteNode(objectProperty.NameNode, outputWriter); + inputNavigator.WriteNode(objectProperty.ValueNode, outputWriter); + } + + outputWriter.WriteObjectEnd(); + break; + + default: + inputNavigator.WriteNode(inputNavigator.GetRootNode(), outputWriter); + break; + } + } + break; + + case RewriteScenario.ReaderAll: + { + IJsonReader inputReader = createReader(inputSpec); + inputReader.WriteAll(outputWriter); + } + break; + + case RewriteScenario.ReaderToken: + { + IJsonReader inputReader = createReader(inputSpec); + while (inputReader.Read()) + { + inputReader.WriteCurrentToken(outputWriter); + } + } + break; + + default: + throw new ArgumentException($"Unexpected {nameof(rewriteScenario)} of type: {rewriteScenario}"); } - return sampledJson; + long executionTime = timer.ElapsedMilliseconds; + + // Compare input to output result + ReadOnlyMemory outputResult = outputWriter.GetResult(); + + byte[] inputBytes = inputResult.ToArray(); + byte[] outputBytes = outputResult.ToArray(); + byte[] expectedOutputBytes = expectedOutputResult.ToArray(); + + StringBuilder verboseOutput = new StringBuilder(); + if (!outputBytes.SequenceEqual(expectedOutputBytes) && + !CompareResults(inputBytes, outputBytes, verboseWriter: new StringWriter(verboseOutput))) + { + string[] inputTextLines = SerializeResultBuffer(inputBytes, inputSpec.SerializationFormat); + string[] outputTextLines = SerializeResultBuffer(outputBytes, outputSpec.SerializationFormat); + + Console.WriteLine($"Rewriting JSON document failed for rewrite scenario '{rewriteScenario}'."); + Console.WriteLine(); + Console.WriteLine($" Input Format : {inputSpec.SerializationFormatToString()}"); + Console.WriteLine($" Input Write Options : {inputSpec.WriteOptions}"); + Console.WriteLine(); + Console.WriteLine($" Output Format : {outputSpec.SerializationFormatToString()}"); + Console.WriteLine($" Output Write Options: {outputSpec.WriteOptions}"); + Console.WriteLine(); + Console.WriteLine($"Comparison Errors:"); + Console.WriteLine(verboseOutput.ToString()); + + Console.WriteLine(); + Console.WriteLine("Input Result:"); + foreach (string line in inputTextLines) Console.WriteLine(line); + Console.WriteLine(); + Console.WriteLine("Output Result:"); + foreach (string line in outputTextLines) Console.WriteLine(line); + + Assert.Fail(); + } + + long verificationTime = timer.ElapsedMilliseconds - executionTime; + + return new RoundTripResult(outputResult, executionTime, verificationTime); + } + + public static bool CompareResults( + byte[] resultBuffer1, + byte[] resultBuffer2, + TextWriter verboseWriter = null) + { + Assert.IsNotNull(resultBuffer1); + Assert.IsNotNull(resultBuffer2); + + // Fast check for identical buffers + if (resultBuffer1.Equals(resultBuffer2)) return true; + + IJsonReader reader1 = JsonReader.Create(resultBuffer1); + IJsonReader reader2 = JsonReader.Create(resultBuffer2); + + int tokenCount = 0; + while (true) + { + bool read1 = reader1.Read(); + bool read2 = reader2.Read(); + + if (read1 != read2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Read method return value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Return Value 1: {read1}"); + verboseWriter.WriteLine($" Return Value 2: {read2}"); + } + + return false; + } + + // If EOF, exit the while loop + if (!read1) break; + + tokenCount++; + + JsonTokenType tokenType1 = reader1.CurrentTokenType; + JsonTokenType tokenType2 = reader2.CurrentTokenType; + + if (tokenType1 != tokenType2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"JSON token type mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Token Type 1: {tokenType1}"); + verboseWriter.WriteLine($" Token Type 2: {tokenType2}"); + } + + return false; + } + + switch (tokenType1) + { + case JsonTokenType.NotStarted: + case JsonTokenType.BeginArray: + case JsonTokenType.EndArray: + case JsonTokenType.BeginObject: + case JsonTokenType.EndObject: + case JsonTokenType.True: + case JsonTokenType.False: + case JsonTokenType.Null: + // No further comparison + break; + + case JsonTokenType.FieldName: + case JsonTokenType.String: + { + string value1 = reader1.GetStringValue(); + string value2 = reader2.GetStringValue(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"String value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Number: + { + Number64 value1 = reader1.GetNumberValue(); + Number64 value2 = reader2.GetNumberValue(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Number value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Int8: + { + sbyte value1 = reader1.GetInt8Value(); + sbyte value2 = reader2.GetInt8Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Int8 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Int16: + { + short value1 = reader1.GetInt16Value(); + short value2 = reader2.GetInt16Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Int16 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Int32: + { + int value1 = reader1.GetInt32Value(); + int value2 = reader2.GetInt32Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Int32 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Int64: + { + long value1 = reader1.GetInt64Value(); + long value2 = reader2.GetInt64Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Int64 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Float32: + { + float value1 = reader1.GetFloat32Value(); + float value2 = reader2.GetFloat32Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Float32 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Float64: + { + double value1 = reader1.GetFloat64Value(); + double value2 = reader2.GetFloat64Value(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Float64 value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Guid: + { + Guid value1 = reader1.GetGuidValue(); + Guid value2 = reader2.GetGuidValue(); + + if (value1 != value2) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"GUID value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + case JsonTokenType.Binary: + { + ReadOnlyMemory value1 = reader1.GetBinaryValue(); + ReadOnlyMemory value2 = reader2.GetBinaryValue(); + + if (value1.ToArray() != value2.ToArray()) + { + if (verboseWriter != null) + { + verboseWriter.WriteLine($"Binary value mismatch at token number {tokenCount}"); + verboseWriter.WriteLine($" Value 1: {value1}"); + verboseWriter.WriteLine($" Value 2: {value2}"); + } + + return false; + } + } + break; + + default: + Assert.Fail($"Unexpected JsonTokenType value {tokenType1}."); + break; + } + } + + return true; + } + + public static string[] SerializeResultBuffer( + byte[] resultBuffer, + JsonSerializationFormat serializationFormat) + { + if (resultBuffer == null) throw new ArgumentNullException(nameof(resultBuffer)); + + const int TextLineSize = 100; + const int RowSize = 16; + + string[] result; + + switch (serializationFormat) + { + case JsonSerializationFormat.Text: + { + string stringResult = Encoding.UTF8.GetString(resultBuffer); + + result = new string[(stringResult.Length + TextLineSize - 1) / TextLineSize]; + for (int i = 0; i < result.Length; i++) + { + int remainingLength = stringResult.Length - (i * TextLineSize); + result[i] = stringResult.Substring(i * TextLineSize, Math.Min(remainingLength, TextLineSize)); + } + } + break; + + case JsonSerializationFormat.Binary: + { + List lines = new List(); + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < resultBuffer.Length; i++) + { + if (i % RowSize == 0) + { + if (stringBuilder.Length > 0) + { + lines.Add(stringBuilder.ToString()); + stringBuilder.Clear(); + } + + stringBuilder.Append(i.ToString("X8")); + } + + if (i % (RowSize / 2) == 0) + { + stringBuilder.Append(' '); + } + + stringBuilder.Append(' ').Append(resultBuffer[i].ToString("X2")); + } + + if (stringBuilder.Length > 0) + { + lines.Add(stringBuilder.ToString()); + } + + result = lines.ToArray(); + } + break; + + default: + Assert.Fail($"Unexpected JsonSerializationFormat: {serializationFormat}."); + result = null; + break; + } + + return result; + } + + public enum RewriteScenario + { + NavigatorRoot, + NavigatorNode, + ReaderAll, + ReaderToken, + }; + + public class SerializationSpec + { + private SerializationSpec(JsonSerializationFormat serializationFormat, JsonWriteOptions writeOptions, bool isNewtonsoft) + { + this.SerializationFormat = serializationFormat; + this.WriteOptions = writeOptions; + this.IsNewtonsoft = isNewtonsoft; + } + + public static SerializationSpec Text(JsonWriteOptions writeOptions = JsonWriteOptions.None) + { + return new SerializationSpec(JsonSerializationFormat.Text, writeOptions, false); + } + + public static SerializationSpec Binary(JsonWriteOptions writeOptions = JsonWriteOptions.None) + { + return new SerializationSpec(JsonSerializationFormat.Binary, writeOptions, false); + } + + public static SerializationSpec Newtonsoft() + { + return new SerializationSpec(JsonSerializationFormat.Text, JsonWriteOptions.None, true); + } + + public string SerializationFormatToString() + { + return this.IsNewtonsoft ? "NewtonsoftText" : this.SerializationFormat.ToString(); + } + + public JsonSerializationFormat SerializationFormat { get; } + public JsonWriteOptions WriteOptions { get; } + public bool IsNewtonsoft { get; } + } + + public class RoundTripResult + { + public RoundTripResult(ReadOnlyMemory outputResult, long executionTime, long verificationTime) + { + this.OutputResult = outputResult; + this.ExecutionTime = executionTime; + this.VerificationTime = verificationTime; + } + + public ReadOnlyMemory OutputResult { get; } + public long ExecutionTime { get; } + public long VerificationTime { get; } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTokenInfo.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTokenInfo.cs index 2f3b7b6aa0..0095a2acff 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTokenInfo.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonTokenInfo.cs @@ -6,19 +6,19 @@ namespace Microsoft.Azure.Cosmos.Tests.Json { using System; + using System.Collections.Generic; using System.Linq; using Microsoft.Azure.Cosmos.Json; internal abstract class JsonToken { - protected JsonToken(JsonTokenType jsonTokenType) - { - this.JsonTokenType = jsonTokenType; - } + public JsonTokenType JsonTokenType { get; } + public bool IsNumberArray { get; } - public JsonTokenType JsonTokenType + protected JsonToken(JsonTokenType jsonTokenType, bool isNumberArray = default) { - get; + this.JsonTokenType = jsonTokenType; + this.IsNumberArray = isNumberArray; } public static JsonToken ArrayStart() @@ -110,6 +110,41 @@ public static JsonToken Binary(ReadOnlyMemory value) { return new JsonBinaryToken(value); } + + public static JsonToken UInt8NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.UInt8, values); + } + + public static JsonToken Int8NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Int8, values); + } + + public static JsonToken Int16NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Int16, values); + } + + public static JsonToken Int32NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Int32, values); + } + + public static JsonToken Int64NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Int64, values); + } + + public static JsonToken Float32NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Float32, values); + } + + public static JsonToken Float64NumberArray(IReadOnlyList values) + { + return new JsonNumberArrayToken(JsonTokenType.Float64, values); + } } internal sealed class JsonStartArrayToken : JsonToken @@ -555,4 +590,30 @@ public override int GetHashCode() return 0; } } + + internal sealed class JsonNumberArrayToken : JsonToken + { + public JsonNumberArrayToken(JsonTokenType jsonTokenType, IReadOnlyList values) + : base(jsonTokenType, isNumberArray: true) + { + this.Values = values; + } + + public IReadOnlyList Values { get; } + + public override bool Equals(object obj) + { + if (obj is JsonNumberArrayToken other) + { + return this.Values.Equals(other.Values); + } + + return false; + } + + public override int GetHashCode() + { + return 0; + } + } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs index 0997b4dfd2..fe660cf10e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs @@ -1,13 +1,14 @@ namespace Microsoft.Azure.Cosmos.Tests.Json { using System; + using System.Buffers; using System.Collections.Generic; + using System.Globalization; using System.Linq; using System.Text; using Microsoft.Azure.Cosmos.Json; using Microsoft.VisualStudio.TestTools.UnitTesting; - using System.Globalization; - using Microsoft.Azure.Cosmos.Core.Utf8; + using static Microsoft.Azure.Cosmos.Tests.Json.JsonTestUtils; [TestClass] public class JsonWriterTests @@ -33,7 +34,6 @@ public void TrueTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -54,7 +54,6 @@ public void FalseTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -75,9 +74,9 @@ public void NullTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } #endregion + #region Numbers [TestMethod] [Owner("mayapainter")] @@ -99,7 +98,6 @@ public void IntegerTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -122,7 +120,6 @@ public void DoubleTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -145,7 +142,6 @@ public void NaNTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -168,7 +164,6 @@ public void PositiveInfinityTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -191,7 +186,6 @@ public void NegativeInfinityTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -214,7 +208,6 @@ public void NegativeNumberTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -237,7 +230,6 @@ public void NumberWithScientificNotationTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -263,7 +255,6 @@ public void NumberRegressionTest() this.VerifyWriter(tokensToWrite, numberValueString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -280,7 +271,7 @@ public void NumberPrecisionTest() List binaryOutputBuilder = new List { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, sizeof(byte) + sizeof(double) + sizeof(byte) + sizeof(double), JsonBinaryEncoding.TypeMarker.NumberDouble }; @@ -299,7 +290,6 @@ public void NumberPrecisionTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -341,6 +331,7 @@ public void LargeNumbersTest() this.VerifyWriter(tokensToWrite, expectedString); } #endregion + #region String [TestMethod] [Owner("mayapainter")] @@ -360,7 +351,6 @@ public void EmptyStringTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -383,7 +373,6 @@ public void StringTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -412,7 +401,6 @@ public void SystemStringTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); systemStringId++; } } @@ -438,17 +426,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -468,17 +445,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -498,17 +464,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -528,17 +483,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -558,17 +502,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -588,17 +521,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -618,17 +540,6 @@ public void DateTimeStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + dateTimeString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(dateTimeString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } } @@ -653,17 +564,6 @@ public void HexStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + hexString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(hexString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -683,17 +583,6 @@ public void HexStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + hexString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(hexString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -714,7 +603,6 @@ public void HexStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - this.VerifyWriter(tokensToWrite, compressedBinaryPayload, null, false); } } @@ -742,17 +630,6 @@ public void CompressedStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + compressedString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(compressedString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -776,17 +653,6 @@ public void CompressedStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + compressedString.Length), - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(compressedString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -813,18 +679,6 @@ public void CompressedStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - JsonBinaryEncoding.TypeMarker.String1ByteLength, - (byte) compressedString.Length - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(compressedString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -854,18 +708,6 @@ public void CompressedStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - JsonBinaryEncoding.TypeMarker.String1ByteLength, - (byte) compressedString.Length - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(compressedString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -916,19 +758,6 @@ public void CompressedStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - JsonBinaryEncoding.TypeMarker.String2ByteLength, - 14, - 1 - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(compressedString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } } @@ -950,26 +779,15 @@ public void GuidStringsTest() } { - byte[] compressedBinaryPayload = - { + byte[] compressedBinaryPayload = + { BinaryFormat, JsonBinaryEncoding.TypeMarker.LowercaseGuidString, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - } - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); + this.VerifyWriter(tokensToWrite, compressedBinaryPayload); } } @@ -992,17 +810,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1024,17 +831,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1056,17 +852,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1088,17 +873,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1120,17 +894,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1152,17 +915,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1183,17 +935,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1215,17 +956,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1247,17 +977,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1278,17 +997,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } { @@ -1310,17 +1018,6 @@ public void GuidStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); this.VerifyWriter(tokensToWrite, compressedBinaryPayload); - - { - List binaryPayload = new List() - { - BinaryFormat, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + guidString.Length) - }; - - binaryPayload.AddRange(Encoding.UTF8.GetBytes(guidString)); - this.VerifyWriter(tokensToWrite, binaryPayload.ToArray(), null, false); - } } } @@ -1343,10 +1040,10 @@ public void ReferenceStringsTest() this.VerifyWriter(tokensToWrite, stringPayload); { - byte[] binaryPayload = - { + byte[] binaryPayload = + { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, 8, (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "hello".Length), (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', @@ -1354,22 +1051,7 @@ public void ReferenceStringsTest() 3, }; - this.VerifyWriter(tokensToWrite, binaryPayload); - } - - { - byte[] binaryPayload = - { - BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, - 12, - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "hello".Length), - (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', - (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "hello".Length), - (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', - }; - - this.VerifyWriter(tokensToWrite, binaryPayload, null, false); + this.VerifyWriter(tokensToWrite, binaryPayload); } } @@ -1598,6 +1280,7 @@ public void ReferenceStringsTest() } } #endregion + #region Array [TestMethod] [Owner("mayapainter")] @@ -1607,7 +1290,7 @@ public void EmptyArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.EmptyArray + JsonBinaryEncoding.TypeMarker.Arr0 }; JsonToken[] tokensToWrite = @@ -1618,7 +1301,6 @@ public void EmptyArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1629,7 +1311,7 @@ public void SingleItemArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.SingleItemArray, + JsonBinaryEncoding.TypeMarker.Arr1, JsonBinaryEncoding.TypeMarker.True }; @@ -1642,7 +1324,6 @@ public void SingleItemArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1652,7 +1333,7 @@ public void IntArrayTest() string expectedString = "[-2,-1,0,1,2]"; List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List numbers = new List @@ -1682,7 +1363,6 @@ public void IntArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1692,7 +1372,7 @@ public void NumberArrayTest() string expectedString = "[15,22,0.1,-0.073,7.70001E+91]"; List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List numbers = new List @@ -1722,7 +1402,6 @@ public void NumberArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1733,7 +1412,7 @@ public void BooleanArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, JsonBinaryEncoding.TypeMarker.True, @@ -1750,7 +1429,6 @@ public void BooleanArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1761,7 +1439,7 @@ public void BooleanLargeArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount, + JsonBinaryEncoding.TypeMarker.ArrLC1, // length 17, // count @@ -1810,7 +1488,6 @@ public void BooleanLargeArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1821,7 +1498,7 @@ public void StringArrayTest() List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List strings = new List @@ -1850,7 +1527,6 @@ public void StringArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1876,7 +1552,7 @@ public void StringLargeArrayTest() List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrLC1 } }; List strings = new List(); @@ -1904,7 +1580,6 @@ public void StringLargeArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1915,7 +1590,7 @@ public void NullArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 3, JsonBinaryEncoding.TypeMarker.Null, @@ -1934,7 +1609,6 @@ public void NullArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1952,7 +1626,7 @@ public void NullLargeArrayTest() List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount }, + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrLC2 }, // length BitConverter.GetBytes((ushort)nullCount), // count @@ -1979,7 +1653,6 @@ public void NullLargeArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -1990,11 +1663,11 @@ public void ObjectArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, - JsonBinaryEncoding.TypeMarker.EmptyObject, - JsonBinaryEncoding.TypeMarker.EmptyObject, + JsonBinaryEncoding.TypeMarker.Obj0, + JsonBinaryEncoding.TypeMarker.Obj0, }; JsonToken[] tokensToWrite = @@ -2009,7 +1682,6 @@ public void ObjectArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -2019,7 +1691,7 @@ public void AllPrimitiveArrayTest() string expectedString = "[0,0,-1,-1.1,1,2,\"hello\",null,true,false]"; List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List elements = new List @@ -2060,7 +1732,6 @@ public void AllPrimitiveArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -2071,11 +1742,11 @@ public void NestedArrayTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.Array1ByteLength, + JsonBinaryEncoding.TypeMarker.ArrL1, // length 2, - JsonBinaryEncoding.TypeMarker.EmptyArray, - JsonBinaryEncoding.TypeMarker.EmptyArray, + JsonBinaryEncoding.TypeMarker.Arr0, + JsonBinaryEncoding.TypeMarker.Arr0, }; JsonToken[] tokensToWrite = @@ -2090,7 +1761,6 @@ public void NestedArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -2114,7 +1784,7 @@ public void StrangeNumberArrayTest() List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ArrL1 } }; List elements = new List @@ -2148,57 +1818,5880 @@ public void StrangeNumberArrayTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } - #endregion Array - #region Escaping + [TestMethod] - [Owner("mayapainter")] - public void EscapeCharacterTest() + [Owner("sboshra")] + public void UniformNumberArrayTest1() { - /// - /// Set of all escape characters in JSON. - /// - Tuple[] escapeCharacters = new Tuple[] - { - new Tuple(@"\b", "\b"), - new Tuple(@"\f", "\f"), - new Tuple(@"\n", "\n"), - new Tuple(@"\r", "\r"), - new Tuple(@"\t", "\t"), - new Tuple(@"\""", "\""), - new Tuple(@"\\", @"\"), - }; + // ------------------------- + // Uniform number arrays + // ------------------------- - foreach (Tuple escapeCharacter in escapeCharacters) + // Int8 Array { - string expectedString = "\"" + escapeCharacter.Item1 + "\""; - JsonToken[] tokensToWrite = { - JsonToken.String(escapeCharacter.Item2), + JsonToken.ArrayStart(), + JsonToken.Number(0), + JsonToken.Number(-5), + JsonToken.Number(5), + JsonToken.Number(32), + JsonToken.Number(-32), + JsonToken.Number(sbyte.MaxValue), + JsonToken.Number(sbyte.MinValue), + JsonToken.ArrayEnd(), }; - this.VerifyWriter(tokensToWrite, expectedString); - // Binary does not test this since you would just put the literal character if you wanted it. - } - } + string[] expectedText = + { + @"[0,-5,5,32,-32,127,-128]" + }; - [TestMethod] - [Owner("mayapainter")] - public void UnicodeEscapeTest() - { - // You don't have to escape a regular unicode character - string expectedString = "\"\x20AC\""; + string[] expectedBinary1 = + { + "00000000 80 E2 0F 00 C9 FB FF 05 C8 20 C9 E0 FF C8 7F C9", + "00000010 80 FF", + }; - JsonToken[] tokensToWrite = + string[] expectedBinary2 = + { + "00000000 80 F0 D8 07 00 FB 05 20 E0 7F 80", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // UInt8 Array { - JsonToken.String("\x20AC"), - }; + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Number(byte.MaxValue), + JsonToken.Number(128), + JsonToken.Number(36), + JsonToken.Number(97), + JsonToken.Number(201), + JsonToken.Number(byte.MaxValue), + JsonToken.Number(byte.MinValue), + JsonToken.Number(30), + JsonToken.Number(1), + JsonToken.ArrayEnd(), + }; - this.VerifyWriter(tokensToWrite, expectedString); - // Binary does not test this since you would just put the literal character if you wanted it. - } + string[] expectedText = + { + @"[255,128,36,97,201,255,0,30,1]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 0F C8 FF C8 80 C8 24 C8 61 C8 C9 C8 FF 00", + "00000010 1E 01", + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 D7 09 FF 80 24 61 C9 FF 00 1E 01", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Int16 Array + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Number(short.MaxValue / 4), + JsonToken.Number(byte.MaxValue), + JsonToken.Number(5), + JsonToken.Number(32), + JsonToken.Number(byte.MinValue), + JsonToken.Number(short.MaxValue), + JsonToken.Number(short.MinValue), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[8191,255,5,32,0,32767,-32768]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 0F C9 FF 1F C8 FF 05 C8 20 00 C9 FF 7F C9", + "00000010 00 80", + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 D9 07 FF 1F FF 00 05 00 20 00 00 00 FF 7F", + "00000010 00 80", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Int32 Array + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Number(int.MaxValue - 1), + JsonToken.Number(byte.MaxValue), + JsonToken.Number(27), + JsonToken.Number(sbyte.MaxValue - 4), + JsonToken.Number(byte.MinValue - 28), + JsonToken.Number(short.MaxValue + 1), + JsonToken.Number(int.MinValue), + JsonToken.Number(int.MaxValue), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[2147483646,255,27,123,-28,32768,-2147483648,2147483647]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 1C CA FE FF FF 7F C8 FF 1B C8 7B C9 E4 FF", + "00000010 CA 00 80 00 00 CA 00 00 00 80 CA FF FF FF 7F", + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 1C CA FE FF FF 7F C8 FF 1B C8 7B C9 E4 FF", + "00000010 CA 00 80 00 00 CA 00 00 00 80 CA FF FF FF 7F", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Int64 Array + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Number(int.MaxValue + 1L), + JsonToken.Number(long.MaxValue / 4), + JsonToken.Number(byte.MinValue), + JsonToken.Number(sbyte.MaxValue), + JsonToken.Number(byte.MinValue), + JsonToken.Number(int.MinValue), + JsonToken.Number(uint.MaxValue), + JsonToken.Number(long.MinValue), + JsonToken.Number(int.MaxValue), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[2147483648,2305843009213693951,0,127,0,-2147483648,4294967295,-9223372036854775808,2147483647]", + }; + + string[] expectedBinary = + { + "00000000 80 E2 32 CB 00 00 00 80 00 00 00 00 CB FF FF FF", + "00000010 FF FF FF FF 1F 00 C8 7F 00 CA 00 00 00 80 CB FF", + "00000020 FF FF FF 00 00 00 00 CB 00 00 00 00 00 00 00 80", + "00000030 CA FF FF FF 7F", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.EnableNumberArrays); + } + + // Float64 Array + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Number(1.1), + JsonToken.Number(3.3), + JsonToken.Number(-2.2), + JsonToken.Number(-4.4), + JsonToken.Number(0), + JsonToken.Number(5.5), + JsonToken.Number(-6.6), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[1.1,3.3,-2.2,-4.4,0,5.5,-6.6]", + }; + + string[] expectedBinary = + { + "00000000 80 E2 37 CC 9A 99 99 99 99 99 F1 3F CC 66 66 66", + "00000010 66 66 66 0A 40 CC 9A 99 99 99 99 99 01 C0 CC 9A", + "00000020 99 99 99 99 99 11 C0 00 CC 00 00 00 00 00 00 16", + "00000030 40 CC 66 66 66 66 66 66 1A C0", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest2() + { + // ------------------------- + // WriteNumberArray + // ------------------------- + + // Empty arrays + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(Int8Array()), + JsonToken.UInt8NumberArray(UInt8Array()), + JsonToken.Int16NumberArray(Int16Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int64NumberArray(Int64Array()), + JsonToken.Float32NumberArray(Float32Array()), + JsonToken.Float64NumberArray(Float64Array()), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[],[],[],[],[],[],[]]" + }; + + string[] expectedBinary = + { + "00000000 80 E2 07 E0 E0 E0 E0 E0 E0 E0" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.EnableNumberArrays); + } + + // Single-item arrays + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(Int8Array(-1)), + JsonToken.UInt8NumberArray(UInt8Array(5)), + JsonToken.Int16NumberArray(Int16Array(16233)), + JsonToken.Int32NumberArray(Int32Array(-16)), + JsonToken.Int64NumberArray(Int64Array(63)), + JsonToken.Float32NumberArray(Float32Array(1.1f)), + JsonToken.Float64NumberArray(Float64Array(-7.7)), + JsonToken.ArrayEnd() + }; + + string[] expectedText = + { + @"[[-1],[5],[16233],[-16],[63],[1.100000023841858],[-7.7]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 25 E1 C9 FF FF E1 05 E1 C9 69 3F E1 C9 F0", + "00000010 FF E1 C8 3F E1 CC 00 00 00 A0 99 99 F1 3F E1 CC", + "00000020 CD CC CC CC CC CC 1E C0" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 31 F0 D8 01 FF F0 D7 01 05 F0 D9 01 69 3F", + "00000010 F0 DA 01 F0 FF FF FF F0 DB 01 3F 00 00 00 00 00", + "00000020 00 00 F0 CD 01 CD CC 8C 3F F0 CE 01 CD CC CC CC", + "00000030 CC CC 1E C0" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Two-item arrays + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(Int8Array(-1, 1)), + JsonToken.UInt8NumberArray(UInt8Array(0, 0)), + JsonToken.Int16NumberArray(Int16Array(1600, -1600)), + JsonToken.Int32NumberArray(Int32Array(-16, 16)), + JsonToken.Int64NumberArray(Int64Array(63, -63)), + JsonToken.Float32NumberArray(Float32Array(1.1f, -1.1f)), + JsonToken.Float64NumberArray(Float64Array(-7.7, 7.7)), + JsonToken.ArrayEnd() + }; + + string[] expectedText = + { + @"[[-1,1],[0,0],[1600,-1600],[-16,16],[63,-63],[1.100000023841858,-1.100000023841858],[-7.7,7.7]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 47 E2 04 C9 FF FF 01 E2 02 00 00 E2 06 C9", + "00000010 40 06 C9 C0 F9 E2 04 C9 F0 FF 10 E2 05 C8 3F C9", + "00000020 C1 FF E2 12 CC 00 00 00 A0 99 99 F1 3F CC 00 00", + "00000030 00 A0 99 99 F1 BF E2 12 CC CD CC CC CC CC CC 1E", + "00000040 C0 CC CD CC CC CC CC CC 1E 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 4D F0 D8 02 FF 01 F0 D7 02 00 00 F0 D9 02", + "00000010 40 06 C0 F9 F0 DA 02 F0 FF FF FF 10 00 00 00 F0", + "00000020 DB 02 3F 00 00 00 00 00 00 00 C1 FF FF FF FF FF", + "00000030 FF FF F0 CD 02 CD CC 8C 3F CD CC 8C BF F0 CE 02", + "00000040 CD CC CC CC CC CC 1E C0 CD CC CC CC CC CC 1E 40", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest3() + { + // ------------------------- + // INT8 number array + // ------------------------- + + sbyte[] values = + { + sbyte.MinValue, + sbyte.MinValue + 1, + sbyte.MinValue + 10, + -10, + -1, + 0, + 1, + 10, + sbyte.MaxValue - 10, + sbyte.MaxValue - 1, + sbyte.MaxValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int8NumberArray(values) + }; + + string[] expectedText = + { + "[-128,-127,-118,-10,-1,0,1,10,117,126,127]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 18 C9 80 FF C9 81 FF C9 8A FF C9 F6 FF C9", + "00000010 FF FF 00 01 0A C8 75 C8 7E C8 7F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 D8 0B 80 81 8A F6 FF 00 01 0A 75 7E 7F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest4() + { + // ------------------------- + // UINT8 number array + // ------------------------- + + byte[] values = + { + byte.MaxValue, + 0, + byte.MaxValue - 1, + 1, + byte.MaxValue - 2, + 2, + byte.MaxValue - 3, + 3, + byte.MaxValue - 4, + 4, + byte.MaxValue - 5, + 5, + byte.MaxValue - 6, + 6, + byte.MaxValue - 7, + 7, + byte.MaxValue - 8, + 8, + byte.MaxValue - 9, + 9, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.UInt8NumberArray(values) + }; + + string[] expectedText = + { + @"[255,0,254,1,253,2,252,3,251,4,250,5,249,6,248,7,247,8,246,9]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 1E 14 C8 FF 00 C8 FE 01 C8 FD 02 C8 FC 03", + "00000010 C8 FB 04 C8 FA 05 C8 F9 06 C8 F8 07 C8 F7 08 C8", + "00000020 F6 09" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 D7 14 FF 00 FE 01 FD 02 FC 03 FB 04 FA 05", + "00000010 F9 06 F8 07 F7 08 F6 09" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest5() + { + // ------------------------- + // INT16 number array + // ------------------------- + + short[] values = { + short.MinValue, + short.MaxValue, + short.MinValue, + sbyte.MaxValue, + sbyte.MinValue, + byte.MaxValue, + 0, + -1000, + 1000, + short.MaxValue, + short.MaxValue, + 0, + 1500, + 0, + 0, + 1500, + 1500, + 1500, + short.MinValue, + short.MinValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int16NumberArray(values) + }; + + string[] expectedText = + { + @"[-32768,32767,-32768,127,-128,255,0,-1000,1000,32767,32767,0,1500,0,0,1500,1500,1500,-32768,-32768]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 32 14 C9 00 80 C9 FF 7F C9 00 80 C8 7F C9", + "00000010 80 FF C8 FF 00 C9 18 FC C9 E8 03 C9 FF 7F C9 FF", + "00000020 7F 00 C9 DC 05 00 00 C9 DC 05 C9 DC 05 C9 DC 05", + "00000030 C9 00 80 C9 00 80" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 D9 14 00 80 FF 7F 00 80 7F 00 80 FF FF 00", + "00000010 00 00 18 FC E8 03 FF 7F FF 7F 00 00 DC 05 00 00", + "00000020 00 00 DC 05 DC 05 DC 05 00 80 00 80" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest6() + { + // ------------------------- + // INT32 number array + // ------------------------- + + // Case 1 + { + int[] values = { + short.MinValue, + short.MaxValue, + 0, + int.MinValue, + int.MaxValue, + 0, + sbyte.MaxValue, + sbyte.MinValue, + 0, + -1000, + 1000, + 0, + short.MaxValue, + short.MaxValue, + 0, + 1500, + -1500, + 0, + 22222222, + -22222222, + 0, + int.MinValue, + int.MinValue, + 0, + int.MaxValue, + int.MaxValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int32NumberArray(values) + }; + + string[] expectedText = + { + @"[-32768,32767,0,-2147483648,2147483647,0,127,-128,0,-1000,1000,0,32767,32767,0,1500,-1500,0,22222222", + @",-22222222,0,-2147483648,-2147483648,0,2147483647,2147483647]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 4D 1A C9 00 80 C9 FF 7F 00 CA 00 00 00 80", + "00000010 CA FF FF FF 7F 00 C8 7F C9 80 FF 00 C9 18 FC C9", + "00000020 E8 03 00 C9 FF 7F C9 FF 7F 00 C9 DC 05 C9 24 FA", + "00000030 00 CA 8E 15 53 01 CA 72 EA AC FE 00 CA 00 00 00", + "00000040 80 CA 00 00 00 80 00 CA FF FF FF 7F CA FF FF FF", + "00000050 7F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 DA 1A 00 80 FF FF FF 7F 00 00 00 00 00 00", + "00000010 00 00 00 80 FF FF FF 7F 00 00 00 00 7F 00 00 00", + "00000020 80 FF FF FF 00 00 00 00 18 FC FF FF E8 03 00 00", + "00000030 00 00 00 00 FF 7F 00 00 FF 7F 00 00 00 00 00 00", + "00000040 DC 05 00 00 24 FA FF FF 00 00 00 00 8E 15 53 01", + "00000050 72 EA AC FE 00 00 00 00 00 00 00 80 00 00 00 80", + "00000060 00 00 00 00 FF FF FF 7F FF FF FF 7F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + int[] values = { + (int)short.MinValue + 1, + (int)short.MaxValue - 1, + -1, + -1, + int.MinValue, + int.MaxValue, + int.MinValue, + int.MaxValue, + -1000, + 1000, + (int)short.MinValue + 1, + (int)short.MaxValue - 1, + 150000, + -150000, + 22222222, + -22222222, + int.MinValue, + int.MinValue, + int.MaxValue, + int.MaxValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int32NumberArray(values) + }; + + string[] expectedText = + { + @"[-32767,32766,-1,-1,-2147483648,2147483647,-2147483648,2147483647,-1000,1000,-32767,32766,150000,-15", + @"0000,22222222,-22222222,-2147483648,-2147483648,2147483647,2147483647]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 54 14 C9 01 80 C9 FE 7F C9 FF FF C9 FF FF", + "00000010 CA 00 00 00 80 CA FF FF FF 7F CA 00 00 00 80 CA", + "00000020 FF FF FF 7F C9 18 FC C9 E8 03 C9 01 80 C9 FE 7F", + "00000030 CA F0 49 02 00 CA 10 B6 FD FF CA 8E 15 53 01 CA", + "00000040 72 EA AC FE CA 00 00 00 80 CA 00 00 00 80 CA FF", + "00000050 FF FF 7F CA FF FF FF 7F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 DA 14 01 80 FF FF FE 7F 00 00 FF FF FF FF", + "00000010 FF FF FF FF 00 00 00 80 FF FF FF 7F 00 00 00 80", + "00000020 FF FF FF 7F 18 FC FF FF E8 03 00 00 01 80 FF FF", + "00000030 FE 7F 00 00 F0 49 02 00 10 B6 FD FF 8E 15 53 01", + "00000040 72 EA AC FE 00 00 00 80 00 00 00 80 FF FF FF 7F", + "00000050 FF FF FF 7F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest7() + { + // ------------------------- + // INT64 number array + // ------------------------- + + // Case 1 + { + long[] values = { + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + short.MinValue, + long.MaxValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int64NumberArray(values) + }; + + string[] expectedText = + { + @"[9223372036854775807,-32768,9223372036854775807,-32768,9223372036854775807,-32768,922337203685477580", + @"7,-32768,9223372036854775807,-32768,9223372036854775807,-32768,9223372036854775807,-32768,9223372036", + @"854775807,-32768,9223372036854775807,-32768,9223372036854775807,-32768,9223372036854775807,-32768,92", + @"23372036854775807,-32768,9223372036854775807]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 99 19 CB FF FF FF FF FF FF FF 7F C9 00 80", + "00000010 CB FF FF FF FF FF FF FF 7F C9 00 80 CB FF FF FF", + "00000020 FF FF FF FF 7F C9 00 80 CB FF FF FF FF FF FF FF", + "00000030 7F C9 00 80 CB FF FF FF FF FF FF FF 7F C9 00 80", + "00000040 CB FF FF FF FF FF FF FF 7F C9 00 80 CB FF FF FF", + "00000050 FF FF FF FF 7F C9 00 80 CB FF FF FF FF FF FF FF", + "00000060 7F C9 00 80 CB FF FF FF FF FF FF FF 7F C9 00 80", + "00000070 CB FF FF FF FF FF FF FF 7F C9 00 80 CB FF FF FF", + "00000080 FF FF FF FF 7F C9 00 80 CB FF FF FF FF FF FF FF", + "00000090 7F C9 00 80 CB FF FF FF FF FF FF FF 7F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 DB 19 FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000010 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000020 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000030 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000040 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000050 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000060 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000070 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000080 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "00000090 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "000000A0 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "000000B0 FF FF FF FF FF FF FF FF FF FF FF 7F 00 80 FF FF", + "000000C0 FF FF FF FF FF FF FF FF FF FF FF 7F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + long[] values = { + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + long.MaxValue, + long.MaxValue, + int.MinValue, + long.MaxValue, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Int64NumberArray(values) + }; + + string[] expectedText = + { + @"[9223372036854775807,9223372036854775807,9223372036854775807,-2147483648,9223372036854775807,9223372", + @"036854775807,9223372036854775807,-2147483648,9223372036854775807,9223372036854775807,922337203685477", + @"5807,-2147483648,9223372036854775807,9223372036854775807,9223372036854775807,-2147483648,92233720368", + @"54775807,9223372036854775807,9223372036854775807,-2147483648,9223372036854775807,9223372036854775807", + @",9223372036854775807,-2147483648,9223372036854775807]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E5 C9 19 CB FF FF FF FF FF FF FF 7F CB FF FF", + "00000010 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "00000020 00 00 00 80 CB FF FF FF FF FF FF FF 7F CB FF FF", + "00000030 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "00000040 00 00 00 80 CB FF FF FF FF FF FF FF 7F CB FF FF", + "00000050 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "00000060 00 00 00 80 CB FF FF FF FF FF FF FF 7F CB FF FF", + "00000070 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "00000080 00 00 00 80 CB FF FF FF FF FF FF FF 7F CB FF FF", + "00000090 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "000000A0 00 00 00 80 CB FF FF FF FF FF FF FF 7F CB FF FF", + "000000B0 FF FF FF FF FF 7F CB FF FF FF FF FF FF FF 7F CA", + "000000C0 00 00 00 80 CB FF FF FF FF FF FF FF 7F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 DB 19 FF FF FF FF FF FF FF 7F FF FF FF FF", + "00000010 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "00000020 FF FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF", + "00000030 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "00000040 FF FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF", + "00000050 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "00000060 FF FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF", + "00000070 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "00000080 FF FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF", + "00000090 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "000000A0 FF FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF", + "000000B0 FF FF FF 7F FF FF FF FF FF FF FF 7F 00 00 00 80", + "000000C0 FF FF FF FF FF FF FF FF FF FF FF 7F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest8() + { + // ------------------------- + // FLOAT32 number array + // ------------------------- + + // Case 1 + { + float[] values = { + 0.010706271976232529f, + -0.00673653045669198f, + 0.010706271976232529f, + -0.00673653045669198f, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Float32NumberArray(values) + }; + + string[] expectedText = + { + @"[0.010706271976232529,-0.00673653045669198,0.010706271976232529,-0.00673653045669198]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 24 CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 A0 C3 97 7B BF CC 00 00 00 80 2B ED 85 3F CC 00", + "00000020 00 00 A0 C3 97 7B BF" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 CD 04 5C 69 2F 3C 1D BE DC BB 5C 69 2F 3C", + "00000010 1D BE DC BB" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + float[] values = { + 0.010706271976232529f, + 0.007289888337254524f, + 0.0f, + (float)int.MaxValue, + 0.0f, + -0.00673653045669198f, + -0.02682582661509514f, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Float32NumberArray(values) + }; + + string[] expectedText = + { + @"[0.010706271976232529,0.007289888337254524,0,2147483648,0,-0.00673653045669198,-0.02682582661509514]" + }; + + string[] expectedBinary1 = + { +#if BACKEND_BINARY_OUTPUT // Double vs. Int64 encoding difference + "00000000 80 E2 2F CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 80 00 DC 7D 3F 00 CC 00 00 00 00 00 00 E0 41 00", + "00000020 CC 00 00 00 A0 C3 97 7B BF CC 00 00 00 C0 3A 78", + "00000030 9B BF" +#else + "00000000 80 E2 3F CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 80 00 DC 7D 3F CC 00 00 00 00 00 00 00 00 CC 00", + "00000020 00 00 00 00 00 E0 41 CC 00 00 00 00 00 00 00 00", + "00000030 CC 00 00 00 A0 C3 97 7B BF CC 00 00 00 C0 3A 78", + "00000040 9B BF" +#endif + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 CD 07 5C 69 2F 3C 04 E0 EE 3B 00 00 00 00", + "00000010 00 00 00 4F 00 00 00 00 1D BE DC BB D6 C1 DB BC" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformNumberArrayTest9() + { + // ------------------------- + // FLOAT64 number array + // ------------------------- + + // Case 1 + { + double[] values = { + 0.010706271976232529, + -0.00673653045669198, + 0.010706271976232529, + -0.00673653045669198, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Float64NumberArray(values) + }; + + string[] expectedText = + { + @"[0.010706271976232529,-0.00673653045669198,0.010706271976232529,-0.00673653045669198]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 24 CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 A0 C3 97 7B BF CC 00 00 00 80 2B ED 85 3F CC 00", + "00000020 00 00 A0 C3 97 7B BF" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 CE 04 00 00 00 80 2B ED 85 3F 00 00 00 A0", + "00000010 C3 97 7B BF 00 00 00 80 2B ED 85 3F 00 00 00 A0", + "00000020 C3 97 7B BF" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + double[] values = { + 0.010706271976232529, + 0.007289888337254524, + (double)int.MinValue - 1.0, + (double)int.MaxValue + 1.0, + (double)int.MinValue - 1.0, + -0.00673653045669198, + -0.02682582661509514, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Float64NumberArray(values) + }; + + string[] expectedText = + { + @"[0.010706271976232529,0.007289888337254524,-2147483649,2147483648,-2147483649,-0.00673653045669198,-", + @"0.02682582661509514]", + }; + + string[] expectedBinary1 = + { +#if BACKEND_BINARY_OUTPUT // Double vs. Int64 encoding difference + "00000000 80 E2 3F CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 80 00 DC 7D 3F CB FF FF FF 7F FF FF FF FF CB 00", + "00000020 00 00 80 00 00 00 00 CB FF FF FF 7F FF FF FF FF", + "00000030 CC 00 00 00 A0 C3 97 7B BF CC 00 00 00 C0 3A 78", + "00000040 9B BF" +#else + "00000000 80 E2 3F CC 00 00 00 80 2B ED 85 3F CC 00 00 00", + "00000010 80 00 DC 7D 3F CC 00 00 20 00 00 00 E0 C1 CC 00", + "00000020 00 00 00 00 00 E0 41 CC 00 00 20 00 00 00 E0 C1", + "00000030 CC 00 00 00 A0 C3 97 7B BF CC 00 00 00 C0 3A 78", + "00000040 9B BF" +#endif + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 CE 07 00 00 00 80 2B ED 85 3F 00 00 00 80", + "00000010 00 DC 7D 3F 00 00 20 00 00 00 E0 C1 00 00 00 00", + "00000020 00 00 E0 41 00 00 20 00 00 00 E0 C1 00 00 00 A0", + "00000030 C3 97 7B BF 00 00 00 C0 3A 78 9B BF" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + double[] values = { + 19.976000, + 31.329000, + 2.368000, + 28.691999, + 21.424999, + 10.555000, + 3.434000, + 16.549000, + 7.441000, + 9.512000, + 30.145000, + 18.059999, + 21.718000, + 3.753000, + 16.139000, + 12.423000, + 16.278999, + 25.996000, + 16.687000, + 12.529000, + 22.549000, + 17.437000, + 19.865999, + 12.949000, + 0.193000, + 23.195000, + 3.297000, + 20.416000, + 28.285999, + 16.105000, + 24.488001, + 16.282000, + 12.455000, + 25.733999, + 18.114000, + 11.701000, + 31.316000, + 20.671000, + 5.786000, + 12.263000, + 4.313000, + 24.355000, + 31.184999, + 20.052999, + 0.912000, + 10.808000, + 1.832000, + 20.945000, + 4.313000, + 27.756001, + 28.320999, + 19.558001, + 23.646000, + 27.982000, + 0.481000, + 4.144000, + 23.195999, + 20.222000, + 7.129000, + 2.161000, + 5.535000, + 20.450001, + 11.173000, + 10.466000, + 12.044000, + 21.659000, + 26.292000, + 26.438999, + 17.253000, + 20.024000, + 26.153999, + 29.510000, + 4.745000, + 20.649000, + 13.186000, + 8.313000, + 4.474000, + 28.021999, + 2.168000, + 14.018000, + 18.787001, + 9.905000, + 17.958000, + 7.391000, + 10.202000, + 3.625000, + 26.476999, + 4.414000, + 9.314000, + 25.823999, + 29.334000, + 25.874001, + 24.372000, + 20.159000, + 11.833000, + 28.070000, + 7.487000, + 28.297001, + 7.518000, + 8.177000 + }; + + JsonToken[] tokensToWrite = + { + JsonToken.Float64NumberArray(values) + }; + + string[] expectedText = + { + @"[19.976,31.329,2.368,28.691999,21.424999,10.555,3.434,16.549,7.441,9.512,30.145,18.059999,21.718,3.7", + @"53,16.139,12.423,16.278999,25.996,16.687,12.529,22.549,17.437,19.865999,12.949,0.193,23.195,3.297,20", + @".416,28.285999,16.105,24.488001,16.282,12.455,25.733999,18.114,11.701,31.316,20.671,5.786,12.263,4.3", + @"13,24.355,31.184999,20.052999,0.912,10.808,1.832,20.945,4.313,27.756001,28.320999,19.558001,23.646,2", + @"7.982,0.481,4.144,23.195999,20.222,7.129,2.161,5.535,20.450001,11.173,10.466,12.044,21.659,26.292,26", + @".438999,17.253,20.024,26.153999,29.51,4.745,20.649,13.186,8.313,4.474,28.021999,2.168,14.018,18.7870", + @"01,9.905,17.958,7.391,10.202,3.625,26.476999,4.414,9.314,25.823999,29.334,25.874001,24.372,20.159,11", + @".833,28.07,7.487,28.297001,7.518,8.177]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E6 84 03 64 00 CC 60 E5 D0 22 DB F9 33 40 CC", + "00000010 4E 62 10 58 39 54 3F 40 CC 8B 6C E7 FB A9 F1 02", + "00000020 40 CC 5D DD B1 D8 26 B1 3C 40 CC 2C D5 05 BC CC", + "00000030 6C 35 40 CC 5C 8F C2 F5 28 1C 25 40 CC 46 B6 F3", + "00000040 FD D4 78 0B 40 CC 06 81 95 43 8B 8C 30 40 CC DD", + "00000050 24 06 81 95 C3 1D 40 CC A0 1A 2F DD 24 06 23 40", + "00000060 CC 85 EB 51 B8 1E 25 3E 40 CC EF CA 2E 18 5C 0F", + "00000070 32 40 CC 2B 87 16 D9 CE B7 35 40 CC A0 1A 2F DD", + "00000080 24 06 0E 40 CC DD 24 06 81 95 23 30 40 CC 7F 6A", + "00000090 BC 74 93 D8 28 40 CC E0 9D 7C 7A 6C 47 30 40 CC", + "000000A0 E5 D0 22 DB F9 FE 39 40 CC 1D 5A 64 3B DF AF 30", + "000000B0 40 CC 02 2B 87 16 D9 0E 29 40 CC 06 81 95 43 8B", + "000000C0 8C 36 40 CC 1D 5A 64 3B DF 6F 31 40 CC 63 5E 47", + "000000D0 1C B2 DD 33 40 CC D9 CE F7 53 E3 E5 29 40 CC 4E", + "000000E0 62 10 58 39 B4 C8 3F CC 52 B8 1E 85 EB 31 37 40", + "000000F0 CC C7 4B 37 89 41 60 0A 40 CC D1 22 DB F9 7E 6A", + "00000100 34 40 CC 4F B0 FF 3A 37 49 3C 40 CC 7B 14 AE 47", + "00000110 E1 1A 30 40 CC 51 6A 2F A2 ED 7C 38 40 CC D5 78", + "00000120 E9 26 31 48 30 40 CC 29 5C 8F C2 F5 E8 28 40 CC", + "00000130 F5 4B C4 5B E7 BB 39 40 CC 77 BE 9F 1A 2F 1D 32", + "00000140 40 CC F4 FD D4 78 E9 66 27 40 CC 37 89 41 60 E5", + "00000150 50 3F 40 CC B2 9D EF A7 C6 AB 34 40 CC BE 9F 1A", + "00000160 2F DD 24 17 40 CC 2D B2 9D EF A7 86 28 40 CC 8D", + "00000170 97 6E 12 83 40 11 40 CC 7B 14 AE 47 E1 5A 38 40", + "00000180 CC EF CA 2E 18 5C 2F 3F 40 CC 80 B8 AB 57 91 0D", + "00000190 34 40 CC C9 76 BE 9F 1A 2F ED 3F CC 04 56 0E 2D", + "000001A0 B2 9D 25 40 CC 1D 5A 64 3B DF 4F FD 3F CC 52 B8", + "000001B0 1E 85 EB F1 34 40 CC 8D 97 6E 12 83 40 11 40 CC", + "000001C0 49 BE 12 48 89 C1 3B 40 CC 78 0C 8F FD 2C 52 3C", + "000001D0 40 CC A3 22 4E 27 D9 8E 33 40 CC 4C 37 89 41 60", + "000001E0 A5 37 40 CC 08 AC 1C 5A 64 FB 3B 40 CC 62 10 58", + "000001F0 39 B4 C8 DE 3F CC FA 7E 6A BC 74 93 10 40 CC 78", + "00000200 0C 8F FD 2C 32 37 40 CC 46 B6 F3 FD D4 38 34 40", + "00000210 CC 6A BC 74 93 18 84 1C 40 CC 7D 3F 35 5E BA 49", + "00000220 01 40 CC A4 70 3D 0A D7 23 16 40 CC D4 2A FA 43", + "00000230 33 73 34 40 CC 7F 6A BC 74 93 58 26 40 CC 3B DF", + "00000240 4F 8D 97 EE 24 40 CC 4A 0C 02 2B 87 16 28 40 CC", + "00000250 62 10 58 39 B4 A8 35 40 CC 98 6E 12 83 C0 4A 3A", + "00000260 40 CC 09 FA 0B 3D 62 70 3A 40 CC 54 E3 A5 9B C4", + "00000270 40 31 40 CC A0 1A 2F DD 24 06 34 40 CC E0 9D 7C", + "00000280 7A 6C 27 3A 40 CC C3 F5 28 5C 8F 82 3D 40 CC 7B", + "00000290 14 AE 47 E1 FA 12 40 CC A0 1A 2F DD 24 A6 34 40", + "000002A0 CC AC 1C 5A 64 3B 5F 2A 40 CC C7 4B 37 89 41 A0", + "000002B0 20 40 CC 4C 37 89 41 60 E5 11 40 CC 72 8B F9 B9", + "000002C0 A1 05 3C 40 CC F2 D2 4D 62 10 58 01 40 CC F0 A7", + "000002D0 C6 4B 37 09 2C 40 CC 57 EB C4 E5 78 C9 32 40 CC", + "000002E0 8F C2 F5 28 5C CF 23 40 CC 68 91 ED 7C 3F F5 31", + "000002F0 40 CC AA F1 D2 4D 62 90 1D 40 CC 81 95 43 8B 6C", + "00000300 67 24 40 CC 00 00 00 00 00 00 0D 40 CC 86 39 41", + "00000310 9B 1C 7A 3A 40 CC 0E 2D B2 9D EF A7 11 40 CC 54", + "00000320 E3 A5 9B C4 A0 22 40 CC CC EF 34 99 F1 D2 39 40", + "00000330 CC 2F DD 24 06 81 55 3D 40 CC DA AB 8F 87 BE DF", + "00000340 39 40 CC AC 1C 5A 64 3B 5F 38 40 CC 62 10 58 39", + "00000350 B4 28 34 40 CC D1 22 DB F9 7E AA 27 40 CC 52 B8", + "00000360 1E 85 EB 11 3C 40 CC A6 9B C4 20 B0 F2 1D 40 CC", + "00000370 1A E1 ED 41 08 4C 3C 40 CC DF 4F 8D 97 6E 12 1E", + "00000380 40 CC B4 C8 76 BE 9F 5A 20 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 F0 CE 64 60 E5 D0 22 DB F9 33 40 4E 62 10 58", + "00000010 39 54 3F 40 8B 6C E7 FB A9 F1 02 40 5D DD B1 D8", + "00000020 26 B1 3C 40 2C D5 05 BC CC 6C 35 40 5C 8F C2 F5", + "00000030 28 1C 25 40 46 B6 F3 FD D4 78 0B 40 06 81 95 43", + "00000040 8B 8C 30 40 DD 24 06 81 95 C3 1D 40 A0 1A 2F DD", + "00000050 24 06 23 40 85 EB 51 B8 1E 25 3E 40 EF CA 2E 18", + "00000060 5C 0F 32 40 2B 87 16 D9 CE B7 35 40 A0 1A 2F DD", + "00000070 24 06 0E 40 DD 24 06 81 95 23 30 40 7F 6A BC 74", + "00000080 93 D8 28 40 E0 9D 7C 7A 6C 47 30 40 E5 D0 22 DB", + "00000090 F9 FE 39 40 1D 5A 64 3B DF AF 30 40 02 2B 87 16", + "000000A0 D9 0E 29 40 06 81 95 43 8B 8C 36 40 1D 5A 64 3B", + "000000B0 DF 6F 31 40 63 5E 47 1C B2 DD 33 40 D9 CE F7 53", + "000000C0 E3 E5 29 40 4E 62 10 58 39 B4 C8 3F 52 B8 1E 85", + "000000D0 EB 31 37 40 C7 4B 37 89 41 60 0A 40 D1 22 DB F9", + "000000E0 7E 6A 34 40 4F B0 FF 3A 37 49 3C 40 7B 14 AE 47", + "000000F0 E1 1A 30 40 51 6A 2F A2 ED 7C 38 40 D5 78 E9 26", + "00000100 31 48 30 40 29 5C 8F C2 F5 E8 28 40 F5 4B C4 5B", + "00000110 E7 BB 39 40 77 BE 9F 1A 2F 1D 32 40 F4 FD D4 78", + "00000120 E9 66 27 40 37 89 41 60 E5 50 3F 40 B2 9D EF A7", + "00000130 C6 AB 34 40 BE 9F 1A 2F DD 24 17 40 2D B2 9D EF", + "00000140 A7 86 28 40 8D 97 6E 12 83 40 11 40 7B 14 AE 47", + "00000150 E1 5A 38 40 EF CA 2E 18 5C 2F 3F 40 80 B8 AB 57", + "00000160 91 0D 34 40 C9 76 BE 9F 1A 2F ED 3F 04 56 0E 2D", + "00000170 B2 9D 25 40 1D 5A 64 3B DF 4F FD 3F 52 B8 1E 85", + "00000180 EB F1 34 40 8D 97 6E 12 83 40 11 40 49 BE 12 48", + "00000190 89 C1 3B 40 78 0C 8F FD 2C 52 3C 40 A3 22 4E 27", + "000001A0 D9 8E 33 40 4C 37 89 41 60 A5 37 40 08 AC 1C 5A", + "000001B0 64 FB 3B 40 62 10 58 39 B4 C8 DE 3F FA 7E 6A BC", + "000001C0 74 93 10 40 78 0C 8F FD 2C 32 37 40 46 B6 F3 FD", + "000001D0 D4 38 34 40 6A BC 74 93 18 84 1C 40 7D 3F 35 5E", + "000001E0 BA 49 01 40 A4 70 3D 0A D7 23 16 40 D4 2A FA 43", + "000001F0 33 73 34 40 7F 6A BC 74 93 58 26 40 3B DF 4F 8D", + "00000200 97 EE 24 40 4A 0C 02 2B 87 16 28 40 62 10 58 39", + "00000210 B4 A8 35 40 98 6E 12 83 C0 4A 3A 40 09 FA 0B 3D", + "00000220 62 70 3A 40 54 E3 A5 9B C4 40 31 40 A0 1A 2F DD", + "00000230 24 06 34 40 E0 9D 7C 7A 6C 27 3A 40 C3 F5 28 5C", + "00000240 8F 82 3D 40 7B 14 AE 47 E1 FA 12 40 A0 1A 2F DD", + "00000250 24 A6 34 40 AC 1C 5A 64 3B 5F 2A 40 C7 4B 37 89", + "00000260 41 A0 20 40 4C 37 89 41 60 E5 11 40 72 8B F9 B9", + "00000270 A1 05 3C 40 F2 D2 4D 62 10 58 01 40 F0 A7 C6 4B", + "00000280 37 09 2C 40 57 EB C4 E5 78 C9 32 40 8F C2 F5 28", + "00000290 5C CF 23 40 68 91 ED 7C 3F F5 31 40 AA F1 D2 4D", + "000002A0 62 90 1D 40 81 95 43 8B 6C 67 24 40 00 00 00 00", + "000002B0 00 00 0D 40 86 39 41 9B 1C 7A 3A 40 0E 2D B2 9D", + "000002C0 EF A7 11 40 54 E3 A5 9B C4 A0 22 40 CC EF 34 99", + "000002D0 F1 D2 39 40 2F DD 24 06 81 55 3D 40 DA AB 8F 87", + "000002E0 BE DF 39 40 AC 1C 5A 64 3B 5F 38 40 62 10 58 39", + "000002F0 B4 28 34 40 D1 22 DB F9 7E AA 27 40 52 B8 1E 85", + "00000300 EB 11 3C 40 A6 9B C4 20 B0 F2 1D 40 1A E1 ED 41", + "00000310 08 4C 3C 40 DF 4F 8D 97 6E 12 1E 40 B4 C8 76 BE", + "00000320 9F 5A 20 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest1() + { + // ------------------------- + // Empty arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.Int32NumberArray(Int32Array()), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[],[],[],[],[],[],[]]" + }; + + string[] expectedBinary = + { + "00000000 80 E2 07 E0 E0 E0 E0 E0 E0 E0" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Int8 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(Int8Array(100)), + JsonToken.Int8NumberArray(Int8Array(102)), + JsonToken.Int8NumberArray(Int8Array(104)), + JsonToken.Int8NumberArray(Int8Array(106)), + JsonToken.Int8NumberArray(Int8Array(108)), + JsonToken.Int8NumberArray(Int8Array(110)), + JsonToken.Int8NumberArray(Int8Array(112)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[100],[102],[104],[106],[108],[110],[112]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 15 E1 C8 64 E1 C8 66 E1 C8 68 E1 C8 6A E1", + "00000010 C8 6C E1 C8 6E E1 C8 70", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D8 01 07 64 66 68 6A 6C 6E 70", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // UInt8 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.UInt8NumberArray(UInt8Array(200)), + JsonToken.UInt8NumberArray(UInt8Array(202)), + JsonToken.UInt8NumberArray(UInt8Array(204)), + JsonToken.UInt8NumberArray(UInt8Array(206)), + JsonToken.UInt8NumberArray(UInt8Array(208)), + JsonToken.UInt8NumberArray(UInt8Array(210)), + JsonToken.UInt8NumberArray(UInt8Array(212)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[200],[202],[204],[206],[208],[210],[212]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 15 E1 C8 C8 E1 C8 CA E1 C8 CC E1 C8 CE E1", + "00000010 C8 D0 E1 C8 D2 E1 C8 D4", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D7 01 07 C8 CA CC CE D0 D2 D4", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Int16 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(Int16Array(5200)), + JsonToken.Int16NumberArray(Int16Array(5202)), + JsonToken.Int16NumberArray(Int16Array(5204)), + JsonToken.Int16NumberArray(Int16Array(5206)), + JsonToken.Int16NumberArray(Int16Array(5208)), + JsonToken.Int16NumberArray(Int16Array(5210)), + JsonToken.Int16NumberArray(Int16Array(5212)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[5200],[5202],[5204],[5206],[5208],[5210],[5212]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 1C E1 C9 50 14 E1 C9 52 14 E1 C9 54 14 E1", + "00000010 C9 56 14 E1 C9 58 14 E1 C9 5A 14 E1 C9 5C 14" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D9 01 07 50 14 52 14 54 14 56 14 58 14", + "00000010 5A 14 5C 14", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Int32 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(Int32Array(845200)), + JsonToken.Int32NumberArray(Int32Array(845202)), + JsonToken.Int32NumberArray(Int32Array(845204)), + JsonToken.Int32NumberArray(Int32Array(845206)), + JsonToken.Int32NumberArray(Int32Array(845208)), + JsonToken.Int32NumberArray(Int32Array(845210)), + JsonToken.Int32NumberArray(Int32Array(845212)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[845200],[845202],[845204],[845206],[845208],[845210],[845212]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 2A E1 CA 90 E5 0C 00 E1 CA 92 E5 0C 00 E1", + "00000010 CA 94 E5 0C 00 E1 CA 96 E5 0C 00 E1 CA 98 E5 0C", + "00000020 00 E1 CA 9A E5 0C 00 E1 CA 9C E5 0C 00", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DA 01 07 90 E5 0C 00 92 E5 0C 00 94 E5", + "00000010 0C 00 96 E5 0C 00 98 E5 0C 00 9A E5 0C 00 9C E5", + "00000020 0C 00", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Int64 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(Int64Array(2709488845200)), + JsonToken.Int64NumberArray(Int64Array(2709488845202)), + JsonToken.Int64NumberArray(Int64Array(2709488845204)), + JsonToken.Int64NumberArray(Int64Array(2709488845206)), + JsonToken.Int64NumberArray(Int64Array(2709488845208)), + JsonToken.Int64NumberArray(Int64Array(2709488845210)), + JsonToken.Int64NumberArray(Int64Array(2709488845212)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + "[[2709488845200],[2709488845202],[2709488845204],[2709488845206],[2709488845208],[2709488845210],[27", + "09488845212]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 46 E1 CB 90 C1 1E DA 76 02 00 00 E1 CB 92", + "00000010 C1 1E DA 76 02 00 00 E1 CB 94 C1 1E DA 76 02 00", + "00000020 00 E1 CB 96 C1 1E DA 76 02 00 00 E1 CB 98 C1 1E", + "00000030 DA 76 02 00 00 E1 CB 9A C1 1E DA 76 02 00 00 E1", + "00000040 CB 9C C1 1E DA 76 02 00 00", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DB 01 07 90 C1 1E DA 76 02 00 00 92 C1", + "00000010 1E DA 76 02 00 00 94 C1 1E DA 76 02 00 00 96 C1", + "00000020 1E DA 76 02 00 00 98 C1 1E DA 76 02 00 00 9A C1", + "00000030 1E DA 76 02 00 00 9C C1 1E DA 76 02 00 00", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Float32 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(Float32Array(1.1f)), + JsonToken.Float32NumberArray(Float32Array(1.2f)), + JsonToken.Float32NumberArray(Float32Array(1.3f)), + JsonToken.Float32NumberArray(Float32Array(1.4f)), + JsonToken.Float32NumberArray(Float32Array(1.5f)), + JsonToken.Float32NumberArray(Float32Array(1.6f)), + JsonToken.Float32NumberArray(Float32Array(1.7f)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[1.100000023841858],[1.2000000476837158],[1.2999999523162842],[1.399999976158142],[1.5],[1.60000002", + @"3841858],[1.7000000476837158]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 46 E1 CC 00 00 00 A0 99 99 F1 3F E1 CC 00", + "00000010 00 00 40 33 33 F3 3F E1 CC 00 00 00 C0 CC CC F4", + "00000020 3F E1 CC 00 00 00 60 66 66 F6 3F E1 CC 00 00 00", + "00000030 00 00 00 F8 3F E1 CC 00 00 00 A0 99 99 F9 3F E1", + "00000040 CC 00 00 00 40 33 33 FB 3F", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CD 01 07 CD CC 8C 3F 9A 99 99 3F 66 66", + "00000010 A6 3F 33 33 B3 3F 00 00 C0 3F CD CC CC 3F 9A 99", + "00000020 D9 3F", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // ------------------------- + // Float64 Single-item Arrays + // ------------------------- + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(Float64Array(1.1)), + JsonToken.Float64NumberArray(Float64Array(1.2)), + JsonToken.Float64NumberArray(Float64Array(1.3)), + JsonToken.Float64NumberArray(Float64Array(1.4)), + JsonToken.Float64NumberArray(Float64Array(1.5)), + JsonToken.Float64NumberArray(Float64Array(1.6)), + JsonToken.Float64NumberArray(Float64Array(1.7)), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[1.1],[1.2],[1.3],[1.4],[1.5],[1.6],[1.7]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 46 E1 CC 9A 99 99 99 99 99 F1 3F E1 CC 33", + "00000010 33 33 33 33 33 F3 3F E1 CC CD CC CC CC CC CC F4", + "00000020 3F E1 CC 66 66 66 66 66 66 F6 3F E1 CC 00 00 00", + "00000030 00 00 00 F8 3F E1 CC 9A 99 99 99 99 99 F9 3F E1", + "00000040 CC 33 33 33 33 33 33 FB 3F", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CE 01 07 9A 99 99 99 99 99 F1 3F 33 33", + "00000010 33 33 33 33 F3 3F CD CC CC CC CC CC F4 3F 66 66", + "00000020 66 66 66 66 F6 3F 00 00 00 00 00 00 F8 3F 9A 99", + "00000030 99 99 99 99 F9 3F 33 33 33 33 33 33 FB 3F", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest2() + { + // ------------------------- + // Int8 Number Arrays + // ------------------------- + + sbyte[] values1 = { -3, -2, -1, 0, 1, 2, 3 }; + sbyte[] values2 = { -10, 0, 10, 20, 30, 40, 50 }; + sbyte[] values3 = { 10, 0, -20, -30, -40, -50, -60 }; + sbyte[] values4 = { -6, -4, -3, 0, 2, 4, 6 }; + + sbyte[] valuesX1 = new sbyte[300]; + sbyte[] valuesX2 = new sbyte[300]; + sbyte[] valuesX3 = new sbyte[300]; + sbyte[] valuesX4 = new sbyte[300]; + + valuesX1[0] = -1; + valuesX2[0] = -2; + valuesX3[0] = -3; + valuesX4[0] = -4; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3,-2,-1,0,1,2,3]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000010 03" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 D8 07 FD FE FF 00 01 02 03" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(values1), + JsonToken.Int8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3,-2,-1,0,1,2,3],[-3,-2,-1,0,1,2,3]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 1E E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01", + "00000010 02 03 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000020 03" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D8 07 02 FD FE FF 00 01 02 03 FD FE FF", + "00000010 00 01 02 03" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(values1), + JsonToken.Int8NumberArray(values2), + JsonToken.Int8NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 2F E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01", + "00000010 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2", + "00000020 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9", + "00000030 C4 FF" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D8 07 03 FD FE FF 00 01 02 03 F6 00 0A", + "00000010 14 1E 28 32 0A 00 EC E2 D8 CE C4" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(values1), + JsonToken.Int8NumberArray(values2), + JsonToken.Int8NumberArray(values3), + JsonToken.Int8NumberArray(values4), + JsonToken.Int8NumberArray(values4), + JsonToken.Int8NumberArray(values3), + JsonToken.Int8NumberArray(values2), + JsonToken.Int8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-6,-4,-3,0", + @",2,4,6],[10,0,-20,-30,-40,-50,-60],[-10,0,10,20,30,40,50],[-3,-2,-1,0,1,2,3]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 7C E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01", + "00000010 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2", + "00000020 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9", + "00000030 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04", + "00000040 06 E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000050 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000060 C9 C4 FF E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000070 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D8 07 08 FD FE FF 00 01 02 03 F6 00 0A", + "00000010 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02", + "00000020 04 06 FA FC FD 00 02 04 06 0A 00 EC E2 D8 CE C4", + "00000030 F6 00 0A 14 1E 28 32 FD FE FF 00 01 02 03" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + sbyte[][] valueSets = { values1, values2, values3, values4 }; + + JsonToken[] tokensToWrite = new JsonToken[1 + 260 + 1]; + + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int i = 0; i < tokensToWrite.Length - 2; i++) + { + tokensToWrite[1 + i] = JsonToken.Int8NumberArray(valueSets[i % valueSets.Length]); + } + tokensToWrite[^1] = JsonToken.ArrayEnd(); + + string[] expectedText = + { + @"[[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0", + @",1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10", + @",0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,", + @"40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0", + @",-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40", + @",-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-", + @"6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,", + @"4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,", + @"-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],", + @"[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20", + @",30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[", + @"10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30", + @",-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60", + @"],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,", + @"0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3", + @",-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2", + @",3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,1", + @"0,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,5", + @"0],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20", + @",-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50", + @",-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4", + @",-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6]", + @",[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0", + @",1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10", + @",0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,", + @"40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0", + @",-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40", + @",-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-", + @"6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,", + @"4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,", + @"-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],", + @"[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20", + @",30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[", + @"10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30", + @",-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60", + @"],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,", + @"0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3", + @",-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2", + @",3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,1", + @"0,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,5", + @"0],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20", + @",-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50", + @",-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4", + @",-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6]", + @",[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0", + @",1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10", + @",0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,", + @"40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0", + @",-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40", + @",-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-", + @"6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,", + @"4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,", + @"-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],", + @"[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20", + @",30,40,50],[10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[", + @"10,0,-20,-30,-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30", + @",-40,-50,-60],[-6,-4,-3,0,2,4,6],[-3,-2,-1,0,1,2,3],[-10,0,10,20,30,40,50],[10,0,-20,-30,-40,-50,-60", + @"],[-6,-4,-3,0,2,4,6]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E6 BE 0F 04 01 E2 0D C9 FD FF C9 FE FF C9 FF", + "00000010 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000020 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000030 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000040 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000050 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000060 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000070 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000080 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000090 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "000000A0 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "000000B0 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "000000C0 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "000000D0 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "000000E0 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "000000F0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "00000100 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "00000110 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000120 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000130 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000140 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000150 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000160 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000170 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000180 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000190 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "000001A0 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "000001B0 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "000001C0 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "000001D0 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "000001E0 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "000001F0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "00000200 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000210 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000220 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000230 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000240 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000250 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000260 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000270 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000280 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000290 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "000002A0 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "000002B0 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "000002C0 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "000002D0 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "000002E0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "000002F0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "00000300 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000310 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000320 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000330 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000340 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000350 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000360 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000370 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000380 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000390 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "000003A0 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "000003B0 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "000003C0 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "000003D0 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "000003E0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "000003F0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000400 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000410 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000420 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000430 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000440 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000450 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000460 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000470 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000480 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000490 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "000004A0 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "000004B0 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "000004C0 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "000004D0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "000004E0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "000004F0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000500 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000510 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000520 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000530 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000540 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000550 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000560 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000570 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000580 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000590 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "000005A0 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "000005B0 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "000005C0 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "000005D0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "000005E0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "000005F0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000600 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000610 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000620 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000630 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000640 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000650 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000660 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000670 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000680 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000690 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "000006A0 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "000006B0 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "000006C0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "000006D0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "000006E0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "000006F0 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000700 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000710 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000720 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000730 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000740 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000750 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000760 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000770 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000780 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "00000790 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "000007A0 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "000007B0 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "000007C0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "000007D0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "000007E0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "000007F0 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000800 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000810 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000820 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000830 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000840 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000850 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000860 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000870 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000880 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "00000890 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "000008A0 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "000008B0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "000008C0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "000008D0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "000008E0 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "000008F0 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000900 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000910 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000920 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000930 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000940 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000950 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000960 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000970 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "00000980 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "00000990 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "000009A0 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "000009B0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "000009C0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "000009D0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "000009E0 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "000009F0 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000A00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000A10 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000A20 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000A30 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000A40 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000A50 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000A60 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000A70 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "00000A80 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "00000A90 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "00000AA0 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "00000AB0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "00000AC0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000AD0 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000AE0 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000AF0 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000B00 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000B10 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000B20 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000B30 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000B40 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000B50 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000B60 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "00000B70 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "00000B80 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "00000B90 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "00000BA0 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "00000BB0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000BC0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000BD0 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000BE0 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000BF0 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000C00 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000C10 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000C20 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000C30 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000C40 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000C50 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000C60 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "00000C70 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "00000C80 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "00000C90 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "00000CA0 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "00000CB0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000CC0 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000CD0 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000CE0 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000CF0 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000D00 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000D10 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000D20 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000D30 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000D40 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000D50 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "00000D60 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "00000D70 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "00000D80 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "00000D90 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "00000DA0 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000DB0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000DC0 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000DD0 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00", + "00000DE0 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32", + "00000DF0 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF", + "00000E00 C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02", + "00000E10 04 06 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02", + "00000E20 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11", + "00000E30 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4", + "00000E40 FF E2 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06", + "00000E50 E2 0D C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2", + "00000E60 0B C9 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00", + "00000E70 C9 EC FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2", + "00000E80 0D C9 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D", + "00000E90 C9 FD FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9", + "00000EA0 F6 FF 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC", + "00000EB0 FF C9 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9", + "00000EC0 FA FF C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD", + "00000ED0 FF C9 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF", + "00000EE0 00 0A 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9", + "00000EF0 E2 FF C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF", + "00000F00 C9 FC FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9", + "00000F10 FE FF C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A", + "00000F20 14 1E C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF", + "00000F30 C9 D8 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC", + "00000F40 FF C9 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF", + "00000F50 C9 FF FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E", + "00000F60 C8 28 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8", + "00000F70 FF C9 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9", + "00000F80 FD FF 00 02 04 06 E2 0D C9 FD FF C9 FE FF C9 FF", + "00000F90 FF 00 01 02 03 E2 0B C9 F6 FF 00 0A 14 1E C8 28", + "00000FA0 C8 32 E2 11 0A 00 C9 EC FF C9 E2 FF C9 D8 FF C9", + "00000FB0 CE FF C9 C4 FF E2 0D C9 FA FF C9 FC FF C9 FD FF", + "00000FC0 00 02 04 06" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 D8 07 00 04 01 FD FE FF 00 01 02 03 F6", + "00000010 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000020 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000030 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000040 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000050 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000060 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000070 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000080 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000090 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000000A0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000000B0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000000C0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000000D0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000000E0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000000F0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000100 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000110 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000120 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000130 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000140 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000150 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000160 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000170 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000180 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000190 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000001A0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000001B0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000001C0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000001D0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000001E0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000001F0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000200 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000210 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000220 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000230 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000240 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000250 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000260 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000270 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000280 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000290 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000002A0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000002B0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000002C0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000002D0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000002E0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000002F0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000300 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000310 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000320 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000330 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000340 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000350 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000360 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000370 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000380 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000390 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000003A0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000003B0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000003C0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000003D0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000003E0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000003F0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000400 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000410 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000420 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000430 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000440 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000450 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000460 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000470 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000480 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000490 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000004A0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000004B0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000004C0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000004D0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000004E0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000004F0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000500 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000510 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000520 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000530 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000540 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000550 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000560 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000570 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000580 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000590 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000005A0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "000005B0 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000005C0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000005D0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000005E0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000005F0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000600 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000610 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000620 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000630 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000640 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "00000650 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "00000660 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "00000670 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "00000680 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000690 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "000006A0 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "000006B0 00 02 04 06 FD FE FF 00 01 02 03 F6 00 0A 14 1E", + "000006C0 28 32 0A 00 EC E2 D8 CE C4 FA FC FD 00 02 04 06", + "000006D0 FD FE FF 00 01 02 03 F6 00 0A 14 1E 28 32 0A 00", + "000006E0 EC E2 D8 CE C4 FA FC FD 00 02 04 06 FD FE FF 00", + "000006F0 01 02 03 F6 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE", + "00000700 C4 FA FC FD 00 02 04 06 FD FE FF 00 01 02 03 F6", + "00000710 00 0A 14 1E 28 32 0A 00 EC E2 D8 CE C4 FA FC FD", + "00000720 00 02 04 06" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 6 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(valuesX1), + JsonToken.Int8NumberArray(valuesX1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0],[-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 66 02 E6 2E 01 2C 01 C9 FF FF 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 00 00 00 E6 2E 01 2C 01 C9 FF FF 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000260 00 00 00 00 00 00 00 00 00 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 D8 2C 01 02 00 FF 00 00 00 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 7 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(valuesX1), + JsonToken.Int8NumberArray(valuesX2), + JsonToken.Int8NumberArray(valuesX3), + JsonToken.Int8NumberArray(valuesX4), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0],[-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0],[-3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0],[-4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 CC 04 E6 2E 01 2C 01 C9 FF FF 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 00 00 00 E6 2E 01 2C 01 C9 FE FF 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000260 00 00 00 00 00 00 00 00 00 00 E6 2E 01 2C 01 C9", + "00000270 FD FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 2E 01", + "000003A0 2C 01 C9 FC FF 00 00 00 00 00 00 00 00 00 00 00", + "000003B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 D8 2C 01 04 00 FF 00 00 00 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 FE 00 00 00 00 00 00 00 00 00 00 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000260 FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000380 00 00 00 00 00 00 00 00 00 00 00 00 FC 00 00 00", + "00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004B0 00 00 00 00 00 00 00 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest3() + { + // ------------------------- + // UInt8 Number Arrays + // ------------------------- + + byte[] values1 = { 0, 8, 16, 32, 40, 48, 56, 64 }; + byte[] values2 = { 0, 10, 20, 30, 40, 50, 60, 70 }; + byte[] values3 = { 100, 101, 102, 103, 104, 105, 106, 107 }; + byte[] values4 = { 255, 254, 253, 253, 251, 250, 249, 248 }; + + byte[] valuesS1 = { 0, 1 }; + byte[] valuesS2 = { 1, 2 }; + byte[] valuesS3 = { 2, 3 }; + byte[] valuesS4 = { 3, 4 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.UInt8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[0,8,16,32,40,48,56,64]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 0D 00 08 10 C8 20 C8 28 C8 30 C8 38 C8", + "00000010 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 D7 08 00 08 10 20 28 30 38 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.UInt8NumberArray(values1), + JsonToken.UInt8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[0,8,16,32,40,48,56,64],[0,8,16,32,40,48,56,64]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 1E E2 0D 00 08 10 C8 20 C8 28 C8 30 C8 38", + "00000010 C8 40 E2 0D 00 08 10 C8 20 C8 28 C8 30 C8 38 C8", + "00000020 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D7 08 02 00 08 10 20 28 30 38 40 00 08", + "00000010 10 20 28 30 38 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.UInt8NumberArray(values1), + JsonToken.UInt8NumberArray(values2), + JsonToken.UInt8NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[0,8,16,32,40,48,56,64],[0,10,20,30,40,50,60,70],[100,101,102,103,104,105,106,107]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 2F E2 0D 00 08 10 C8 20 C8 28 C8 30 C8 38", + "00000010 C8 40 E2 0C 00 0A 14 1E C8 28 C8 32 C8 3C C8 46", + "00000020 E2 10 C8 64 C8 65 C8 66 C8 67 C8 68 C8 69 C8 6A", + "00000030 C8 6B" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D7 08 03 00 08 10 20 28 30 38 40 00 0A", + "00000010 14 1E 28 32 3C 46 64 65 66 67 68 69 6A 6B" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.UInt8NumberArray(values1), + JsonToken.UInt8NumberArray(values2), + JsonToken.UInt8NumberArray(values3), + JsonToken.UInt8NumberArray(values4), + JsonToken.UInt8NumberArray(values4), + JsonToken.UInt8NumberArray(values3), + JsonToken.UInt8NumberArray(values2), + JsonToken.UInt8NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[0,8,16,32,40,48,56,64],[0,10,20,30,40,50,60,70],[100,101,102,103,104,105,106,107],[255,254,253,253", + @",251,250,249,248],[255,254,253,253,251,250,249,248],[100,101,102,103,104,105,106,107],[0,10,20,30,40", + @",50,60,70],[0,8,16,32,40,48,56,64]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 82 E2 0D 00 08 10 C8 20 C8 28 C8 30 C8 38", + "00000010 C8 40 E2 0C 00 0A 14 1E C8 28 C8 32 C8 3C C8 46", + "00000020 E2 10 C8 64 C8 65 C8 66 C8 67 C8 68 C8 69 C8 6A", + "00000030 C8 6B E2 10 C8 FF C8 FE C8 FD C8 FD C8 FB C8 FA", + "00000040 C8 F9 C8 F8 E2 10 C8 FF C8 FE C8 FD C8 FD C8 FB", + "00000050 C8 FA C8 F9 C8 F8 E2 10 C8 64 C8 65 C8 66 C8 67", + "00000060 C8 68 C8 69 C8 6A C8 6B E2 0C 00 0A 14 1E C8 28", + "00000070 C8 32 C8 3C C8 46 E2 0D 00 08 10 C8 20 C8 28 C8", + "00000080 30 C8 38 C8 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D7 08 08 00 08 10 20 28 30 38 40 00 0A", + "00000010 14 1E 28 32 3C 46 64 65 66 67 68 69 6A 6B FF FE", + "00000020 FD FD FB FA F9 F8 FF FE FD FD FB FA F9 F8 64 65", + "00000030 66 67 68 69 6A 6B 00 0A 14 1E 28 32 3C 46 00 08", + "00000040 10 20 28 30 38 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + byte[][] valueSets = { valuesS1, valuesS2, valuesS3, valuesS4 }; + + JsonToken[] tokensToWrite = new JsonToken[1 + 260 + 1]; + + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int i = 0; i < tokensToWrite.Length - 2; i++) + { + tokensToWrite[1 + i] = JsonToken.UInt8NumberArray(valueSets[i % valueSets.Length]); + } + tokensToWrite[^1] = JsonToken.ArrayEnd(); + + string[] expectedText = + { + @"[[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,", + @"1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[", + @"1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2]", + @",[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,", + @"3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[", + @"3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4]", + @",[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,", + @"1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[", + @"1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2]", + @",[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,", + @"3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[", + @"3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4]", + @",[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,", + @"1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[", + @"1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2]", + @",[2,3],[3,4],[0,1],[1,2],[2,3],[3,4],[0,1],[1,2],[2,3],[3,4]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E6 10 04 04 01 E2 02 00 01 E2 02 01 02 E2 02", + "00000010 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000020 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000030 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000040 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000050 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000060 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000070 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000080 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000090 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000A0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000B0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000C0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000D0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000E0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000000F0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000100 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000110 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000120 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000130 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000140 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000150 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000160 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000170 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000180 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000190 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001A0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001B0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001C0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001D0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001E0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000001F0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000200 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000210 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000220 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000230 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000240 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000250 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000260 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000270 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000280 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000290 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002A0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002B0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002C0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002D0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002E0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000002F0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000300 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000310 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000320 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000330 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000340 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000350 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000360 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000370 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000380 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000390 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003A0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003B0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003C0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003D0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003E0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "000003F0 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000400 02 03 E2 02 03 04 E2 02 00 01 E2 02 01 02 E2 02", + "00000410 02 03 E2 02 03 04" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 D7 02 00 04 01 00 01 01 02 02 03 03 04", + "00000010 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000020 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000030 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000040 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000050 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000060 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000070 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000080 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000090 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000A0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000B0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000C0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000D0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000E0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000000F0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000100 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000110 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000120 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000130 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000140 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000150 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000160 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000170 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000180 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000190 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001A0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001B0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001C0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001D0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001E0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "000001F0 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + "00000200 00 01 01 02 02 03 03 04 00 01 01 02 02 03 03 04", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest4() + { + // ------------------------- + // Int16 Number Arrays + // ------------------------- + + short[] values1 = { -3000, -2000, -1000, 0, 1000, 2000, 3000 }; + short[] values2 = { 1000, 2000, 3000, 4000, 5000, 6000, 7000 }; + short[] values3 = { -1000, -2000, -3000, -4000, -5000, -6000, -7000 }; + short[] values4 = { 2000, 4000, 6000, 8000, 10000, 12000, 14000 }; + + short[] valuesS1 = { 1024, 2048 }; + short[] valuesS2 = { 2048, 4096 }; + short[] valuesS3 = { 4096, 8192 }; + short[] valuesS4 = { 8192, 1024 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3000,-2000,-1000,0,1000,2000,3000]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 13 C9 48 F4 C9 30 F8 C9 18 FC 00 C9 E8", + "00000010 03 C9 D0 07 C9 B8 0B" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 D9 07 48 F4 30 F8 18 FC 00 00 E8 03 D0", + "00000010 07 B8 0B" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(values1), + JsonToken.Int16NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3000,-2000,-1000,0,1000,2000,3000],[-3000,-2000,-1000,0,1000,2000,3000]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 2A E2 13 C9 48 F4 C9 30 F8 C9 18 FC 00 C9", + "00000010 E8 03 C9 D0 07 C9 B8 0B E2 13 C9 48 F4 C9 30 F8", + "00000020 C9 18 FC 00 C9 E8 03 C9 D0 07 C9 B8 0B" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D9 07 02 48 F4 30 F8 18 FC 00 00 E8 03", + "00000010 D0 07 B8 0B 48 F4 30 F8 18 FC 00 00 E8 03 D0 07", + "00000020 B8 0B" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(values1), + JsonToken.Int16NumberArray(values2), + JsonToken.Int16NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3000,-2000,-1000,0,1000,2000,3000],[1000,2000,3000,4000,5000,6000,7000],[-1000,-2000,-3000,-4000,", + @"-5000,-6000,-7000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 43 E2 13 C9 48 F4 C9 30 F8 C9 18 FC 00 C9", + "00000010 E8 03 C9 D0 07 C9 B8 0B E2 15 C9 E8 03 C9 D0 07", + "00000020 C9 B8 0B C9 A0 0F C9 88 13 C9 70 17 C9 58 1B E2", + "00000030 15 C9 18 FC C9 30 F8 C9 48 F4 C9 60 F0 C9 78 EC", + "00000040 C9 90 E8 C9 A8 E4" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D9 07 03 48 F4 30 F8 18 FC 00 00 E8 03", + "00000010 D0 07 B8 0B E8 03 D0 07 B8 0B A0 0F 88 13 70 17", + "00000020 58 1B 18 FC 30 F8 48 F4 60 F0 78 EC 90 E8 A8 E4", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(values1), + JsonToken.Int16NumberArray(values2), + JsonToken.Int16NumberArray(values3), + JsonToken.Int16NumberArray(values4), + JsonToken.Int16NumberArray(values4), + JsonToken.Int16NumberArray(values3), + JsonToken.Int16NumberArray(values2), + JsonToken.Int16NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3000,-2000,-1000,0,1000,2000,3000],[1000,2000,3000,4000,5000,6000,7000],[-1000,-2000,-3000,-4000,", + @"-5000,-6000,-7000],[2000,4000,6000,8000,10000,12000,14000],[2000,4000,6000,8000,10000,12000,14000],[", + @"-1000,-2000,-3000,-4000,-5000,-6000,-7000],[1000,2000,3000,4000,5000,6000,7000],[-3000,-2000,-1000,0", + @",1000,2000,3000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 B4 E2 13 C9 48 F4 C9 30 F8 C9 18 FC 00 C9", + "00000010 E8 03 C9 D0 07 C9 B8 0B E2 15 C9 E8 03 C9 D0 07", + "00000020 C9 B8 0B C9 A0 0F C9 88 13 C9 70 17 C9 58 1B E2", + "00000030 15 C9 18 FC C9 30 F8 C9 48 F4 C9 60 F0 C9 78 EC", + "00000040 C9 90 E8 C9 A8 E4 E2 15 C9 D0 07 C9 A0 0F C9 70", + "00000050 17 C9 40 1F C9 10 27 C9 E0 2E C9 B0 36 E2 15 C9", + "00000060 D0 07 C9 A0 0F C9 70 17 C9 40 1F C9 10 27 C9 E0", + "00000070 2E C9 B0 36 E2 15 C9 18 FC C9 30 F8 C9 48 F4 C9", + "00000080 60 F0 C9 78 EC C9 90 E8 C9 A8 E4 E2 15 C9 E8 03", + "00000090 C9 D0 07 C9 B8 0B C9 A0 0F C9 88 13 C9 70 17 C9", + "000000A0 58 1B E2 13 C9 48 F4 C9 30 F8 C9 18 FC 00 C9 E8", + "000000B0 03 C9 D0 07 C9 B8 0B" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 D9 07 08 48 F4 30 F8 18 FC 00 00 E8 03", + "00000010 D0 07 B8 0B E8 03 D0 07 B8 0B A0 0F 88 13 70 17", + "00000020 58 1B 18 FC 30 F8 48 F4 60 F0 78 EC 90 E8 A8 E4", + "00000030 D0 07 A0 0F 70 17 40 1F 10 27 E0 2E B0 36 D0 07", + "00000040 A0 0F 70 17 40 1F 10 27 E0 2E B0 36 18 FC 30 F8", + "00000050 48 F4 60 F0 78 EC 90 E8 A8 E4 E8 03 D0 07 B8 0B", + "00000060 A0 0F 88 13 70 17 58 1B 48 F4 30 F8 18 FC 00 00", + "00000070 E8 03 D0 07 B8 0B" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + short[][] valueSets = { valuesS1, valuesS2, valuesS3, valuesS4 }; + + JsonToken[] tokensToWrite = new JsonToken[1 + 260 + 1]; + + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int i = 0; i < tokensToWrite.Length - 2; i++) + { + tokensToWrite[1 + i] = JsonToken.Int16NumberArray(valueSets[i % valueSets.Length]); + } + tokensToWrite[^1] = JsonToken.ArrayEnd(); + + string[] expectedText = + { + @"[[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[10", + @"24,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2", + @"048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048]", + @",[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[20", + @"48,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4", + @"096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096]", + @",[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[40", + @"96,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8", + @"192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192]", + @",[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[81", + @"92,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1", + @"024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024]", + @",[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[10", + @"24,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2", + @"048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048]", + @",[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[20", + @"48,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4", + @"096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096]", + @",[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[40", + @"96,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8", + @"192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192]", + @",[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[81", + @"92,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1", + @"024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024]", + @",[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[10", + @"24,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2", + @"048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048]", + @",[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[20", + @"48,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4", + @"096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096]", + @",[4096,8192],[8192,1024],[1024,2048],[2048,4096],[4096,8192],[8192,1024],[1024,2048],[2048,4096],[40", + @"96,8192],[8192,1024]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E6 20 08 04 01 E2 06 C9 00 04 C9 00 08 E2 06", + "00000010 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000020 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000030 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000040 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000050 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000060 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000070 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000080 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000090 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000000A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000000B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000000C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000000D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000000E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000000F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000100 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000110 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000120 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000130 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000140 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000150 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000160 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000170 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000180 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000190 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000001A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000001B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000001C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000001D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000001E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000001F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000200 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000210 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000220 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000230 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000240 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000250 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000260 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000270 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000280 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000290 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000002A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000002B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000002C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000002D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000002E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000002F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000300 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000310 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000320 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000330 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000340 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000350 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000360 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000370 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000380 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000390 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000003A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000003B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000003C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000003D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000003E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000003F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000400 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000410 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000420 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000430 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000440 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000450 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000460 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000470 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000480 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000490 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000004A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000004B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000004C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000004D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000004E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000004F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000500 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000510 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000520 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000530 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000540 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000550 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000560 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000570 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000580 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000590 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000005A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000005B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000005C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000005D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000005E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000005F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000600 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000610 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000620 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000630 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000640 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000650 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000660 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000670 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000680 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000690 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000006A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000006B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000006C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000006D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000006E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000006F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000700 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000710 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000720 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000730 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000740 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000750 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000760 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000770 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000780 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000790 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000007A0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000007B0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000007C0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000007D0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "000007E0 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "000007F0 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000800 C9 00 20 C9 00 04 E2 06 C9 00 04 C9 00 08 E2 06", + "00000810 C9 00 08 C9 00 10 E2 06 C9 00 10 C9 00 20 E2 06", + "00000820 C9 00 20 C9 00 04" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 D9 02 00 04 01 00 04 00 08 00 08 00 10", + "00000010 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000020 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000030 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000040 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000050 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000060 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000070 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000080 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000090 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000A0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000B0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000C0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000D0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000E0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000000F0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000100 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000110 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000120 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000130 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000140 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000150 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000160 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000170 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000180 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000190 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001A0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001B0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001C0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001D0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001E0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000001F0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000200 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000210 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000220 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000230 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000240 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000250 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000260 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000270 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000280 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000290 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002A0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002B0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002C0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002D0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002E0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000002F0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000300 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000310 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000320 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000330 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000340 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000350 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000360 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000370 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000380 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000390 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003A0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003B0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003C0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003D0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003E0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "000003F0 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000400 00 10 00 20 00 20 00 04 00 04 00 08 00 08 00 10", + "00000410 00 10 00 20 00 20 00 04" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest5() + { + // ------------------------- + // Int32 Number Arrays + // ------------------------- + + int[] values1 = { -300000, -200000, -100000, 0, 100000, 200000 }; + int[] values2 = { 10000, 200000, 300000, 400000, 500000, 600000 }; + int[] values3 = { -100000, -200000, -300000, -400000, -500000, -600000 }; + int[] values4 = { 200000, 400000, 600000, 800000, 1000000, 1200000 }; + + int[] valuesX1 = new int[300]; + int[] valuesX2 = new int[300]; + + valuesX1[0] = -1; + valuesX2[0] = -2; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-300000,-200000,-100000,0,100000,200000]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 1A CA 20 6C FB FF CA C0 F2 FC FF CA 60", + "00000010 79 FE FF 00 CA A0 86 01 00 CA 40 0D 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 DA 06 20 6C FB FF C0 F2 FC FF 60 79 FE", + "00000010 FF 00 00 00 00 A0 86 01 00 40 0D 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(values1), + JsonToken.Int32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-300000,-200000,-100000,0,100000,200000],[-300000,-200000,-100000,0,100000,200000]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 38 E2 1A CA 20 6C FB FF CA C0 F2 FC FF CA", + "00000010 60 79 FE FF 00 CA A0 86 01 00 CA 40 0D 03 00 E2", + "00000020 1A CA 20 6C FB FF CA C0 F2 FC FF CA 60 79 FE FF", + "00000030 00 CA A0 86 01 00 CA 40 0D 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DA 06 02 20 6C FB FF C0 F2 FC FF 60 79", + "00000010 FE FF 00 00 00 00 A0 86 01 00 40 0D 03 00 20 6C", + "00000020 FB FF C0 F2 FC FF 60 79 FE FF 00 00 00 00 A0 86", + "00000030 01 00 40 0D 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(values1), + JsonToken.Int32NumberArray(values2), + JsonToken.Int32NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-300000,-200000,-100000,0,100000,200000],[10000,200000,300000,400000,500000,600000],[-100000,-2000", + @"00,-300000,-400000,-500000,-600000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 5A E2 1A CA 20 6C FB FF CA C0 F2 FC FF CA", + "00000010 60 79 FE FF 00 CA A0 86 01 00 CA 40 0D 03 00 E2", + "00000020 1C C9 10 27 CA 40 0D 03 00 CA E0 93 04 00 CA 80", + "00000030 1A 06 00 CA 20 A1 07 00 CA C0 27 09 00 E2 1E CA", + "00000040 60 79 FE FF CA C0 F2 FC FF CA 20 6C FB FF CA 80", + "00000050 E5 F9 FF CA E0 5E F8 FF CA 40 D8 F6 FF" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DA 06 03 20 6C FB FF C0 F2 FC FF 60 79", + "00000010 FE FF 00 00 00 00 A0 86 01 00 40 0D 03 00 10 27", + "00000020 00 00 40 0D 03 00 E0 93 04 00 80 1A 06 00 20 A1", + "00000030 07 00 C0 27 09 00 60 79 FE FF C0 F2 FC FF 20 6C", + "00000040 FB FF 80 E5 F9 FF E0 5E F8 FF 40 D8 F6 FF" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(values1), + JsonToken.Int32NumberArray(values2), + JsonToken.Int32NumberArray(values3), + JsonToken.Int32NumberArray(values4), + JsonToken.Int32NumberArray(values4), + JsonToken.Int32NumberArray(values3), + JsonToken.Int32NumberArray(values2), + JsonToken.Int32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-300000,-200000,-100000,0,100000,200000],[10000,200000,300000,400000,500000,600000],[-100000,-2000", + @"00,-300000,-400000,-500000,-600000],[200000,400000,600000,800000,1000000,1200000],[200000,400000,600", + @"000,800000,1000000,1200000],[-100000,-200000,-300000,-400000,-500000,-600000],[10000,200000,300000,4", + @"00000,500000,600000],[-300000,-200000,-100000,0,100000,200000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 F4 E2 1A CA 20 6C FB FF CA C0 F2 FC FF CA", + "00000010 60 79 FE FF 00 CA A0 86 01 00 CA 40 0D 03 00 E2", + "00000020 1C C9 10 27 CA 40 0D 03 00 CA E0 93 04 00 CA 80", + "00000030 1A 06 00 CA 20 A1 07 00 CA C0 27 09 00 E2 1E CA", + "00000040 60 79 FE FF CA C0 F2 FC FF CA 20 6C FB FF CA 80", + "00000050 E5 F9 FF CA E0 5E F8 FF CA 40 D8 F6 FF E2 1E CA", + "00000060 40 0D 03 00 CA 80 1A 06 00 CA C0 27 09 00 CA 00", + "00000070 35 0C 00 CA 40 42 0F 00 CA 80 4F 12 00 E2 1E CA", + "00000080 40 0D 03 00 CA 80 1A 06 00 CA C0 27 09 00 CA 00", + "00000090 35 0C 00 CA 40 42 0F 00 CA 80 4F 12 00 E2 1E CA", + "000000A0 60 79 FE FF CA C0 F2 FC FF CA 20 6C FB FF CA 80", + "000000B0 E5 F9 FF CA E0 5E F8 FF CA 40 D8 F6 FF E2 1C C9", + "000000C0 10 27 CA 40 0D 03 00 CA E0 93 04 00 CA 80 1A 06", + "000000D0 00 CA 20 A1 07 00 CA C0 27 09 00 E2 1A CA 20 6C", + "000000E0 FB FF CA C0 F2 FC FF CA 60 79 FE FF 00 CA A0 86", + "000000F0 01 00 CA 40 0D 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DA 06 08 20 6C FB FF C0 F2 FC FF 60 79", + "00000010 FE FF 00 00 00 00 A0 86 01 00 40 0D 03 00 10 27", + "00000020 00 00 40 0D 03 00 E0 93 04 00 80 1A 06 00 20 A1", + "00000030 07 00 C0 27 09 00 60 79 FE FF C0 F2 FC FF 20 6C", + "00000040 FB FF 80 E5 F9 FF E0 5E F8 FF 40 D8 F6 FF 40 0D", + "00000050 03 00 80 1A 06 00 C0 27 09 00 00 35 0C 00 40 42", + "00000060 0F 00 80 4F 12 00 40 0D 03 00 80 1A 06 00 C0 27", + "00000070 09 00 00 35 0C 00 40 42 0F 00 80 4F 12 00 60 79", + "00000080 FE FF C0 F2 FC FF 20 6C FB FF 80 E5 F9 FF E0 5E", + "00000090 F8 FF 40 D8 F6 FF 10 27 00 00 40 0D 03 00 E0 93", + "000000A0 04 00 80 1A 06 00 20 A1 07 00 C0 27 09 00 20 6C", + "000000B0 FB FF C0 F2 FC FF 60 79 FE FF 00 00 00 00 A0 86", + "000000C0 01 00 40 0D 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(valuesX1), + JsonToken.Int32NumberArray(valuesX1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + @",0],[-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,", + @"0,0,0]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 66 02 E6 2E 01 2C 01 C9 FF FF 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 00 00 00 E6 2E 01 2C 01 C9 FF FF 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000260 00 00 00 00 00 00 00 00 00 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 DA 2C 01 02 00 FF FF FF FF 00 00 00 00", + "00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000002F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000003F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004B0 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00", + "000004C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000004F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000590 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000005F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000690 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000006F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000710 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000720 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000730 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000740 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000750 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000760 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000770 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000790 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000007F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "000008F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000920 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000950 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "00000960 00 00 00 00 00 00 00 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest6() + { + // ------------------------- + // Int64 Number Arrays + // ------------------------- + + long[] values1 = { -30000000000, -20000000000, -10000000000, 10000000000 }; + long[] values2 = { 10000000000, 20000000000, 30000000000, 40000000000 }; + long[] values3 = { -10000000000, -20000000000, -30000000000, -40000000000 }; + long[] values4 = { 80000000000, 60000000000, 40000000000, 20000000000 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-30000000000,-20000000000,-10000000000,10000000000]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 24 CB 00 54 DC 03 F9 FF FF FF CB 00 38", + "00000010 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF CB", + "00000020 00 E4 0B 54 02 00 00 00", + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 DB 04 00 54 DC 03 F9 FF FF FF 00 38 E8", + "00000010 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4 0B", + "00000020 54 02 00 00 00", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(values1), + JsonToken.Int64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-30000000000,-20000000000,-10000000000,10000000000],[-30000000000,-20000000000,-10000000000,100000", + @"00000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 4C E2 24 CB 00 54 DC 03 F9 FF FF FF CB 00", + "00000010 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF", + "00000020 CB 00 E4 0B 54 02 00 00 00 E2 24 CB 00 54 DC 03", + "00000030 F9 FF FF FF CB 00 38 E8 57 FB FF FF FF CB 00 1C", + "00000040 F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00 00", + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DB 04 02 00 54 DC 03 F9 FF FF FF 00 38", + "00000010 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000020 0B 54 02 00 00 00 00 54 DC 03 F9 FF FF FF 00 38", + "00000030 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000040 0B 54 02 00 00 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(values1), + JsonToken.Int64NumberArray(values2), + JsonToken.Int64NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-30000000000,-20000000000,-10000000000,10000000000],[10000000000,20000000000,30000000000,400000000", + @"00],[-10000000000,-20000000000,-30000000000,-40000000000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 72 E2 24 CB 00 54 DC 03 F9 FF FF FF CB 00", + "00000010 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF", + "00000020 CB 00 E4 0B 54 02 00 00 00 E2 24 CB 00 E4 0B 54", + "00000030 02 00 00 00 CB 00 C8 17 A8 04 00 00 00 CB 00 AC", + "00000040 23 FC 06 00 00 00 CB 00 90 2F 50 09 00 00 00 E2", + "00000050 24 CB 00 1C F4 AB FD FF FF FF CB 00 38 E8 57 FB", + "00000060 FF FF FF CB 00 54 DC 03 F9 FF FF FF CB 00 70 D0", + "00000070 AF F6 FF FF FF" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DB 04 03 00 54 DC 03 F9 FF FF FF 00 38", + "00000010 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000020 0B 54 02 00 00 00 00 E4 0B 54 02 00 00 00 00 C8", + "00000030 17 A8 04 00 00 00 00 AC 23 FC 06 00 00 00 00 90", + "00000040 2F 50 09 00 00 00 00 1C F4 AB FD FF FF FF 00 38", + "00000050 E8 57 FB FF FF FF 00 54 DC 03 F9 FF FF FF 00 70", + "00000060 D0 AF F6 FF FF FF" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(values1), + JsonToken.Int64NumberArray(values2), + JsonToken.Int64NumberArray(values3), + JsonToken.Int64NumberArray(values4), + JsonToken.Int64NumberArray(values4), + JsonToken.Int64NumberArray(values3), + JsonToken.Int64NumberArray(values2), + JsonToken.Int64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-30000000000,-20000000000,-10000000000,10000000000],[10000000000,20000000000,30000000000,400000000", + @"00],[-10000000000,-20000000000,-30000000000,-40000000000],[80000000000,60000000000,40000000000,20000", + @"000000],[80000000000,60000000000,40000000000,20000000000],[-10000000000,-20000000000,-30000000000,-4", + @"0000000000],[10000000000,20000000000,30000000000,40000000000],[-30000000000,-20000000000,-1000000000", + @"0,10000000000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 30 01 E2 24 CB 00 54 DC 03 F9 FF FF FF CB", + "00000010 00 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF", + "00000020 FF CB 00 E4 0B 54 02 00 00 00 E2 24 CB 00 E4 0B", + "00000030 54 02 00 00 00 CB 00 C8 17 A8 04 00 00 00 CB 00", + "00000040 AC 23 FC 06 00 00 00 CB 00 90 2F 50 09 00 00 00", + "00000050 E2 24 CB 00 1C F4 AB FD FF FF FF CB 00 38 E8 57", + "00000060 FB FF FF FF CB 00 54 DC 03 F9 FF FF FF CB 00 70", + "00000070 D0 AF F6 FF FF FF E2 24 CB 00 20 5F A0 12 00 00", + "00000080 00 CB 00 58 47 F8 0D 00 00 00 CB 00 90 2F 50 09", + "00000090 00 00 00 CB 00 C8 17 A8 04 00 00 00 E2 24 CB 00", + "000000A0 20 5F A0 12 00 00 00 CB 00 58 47 F8 0D 00 00 00", + "000000B0 CB 00 90 2F 50 09 00 00 00 CB 00 C8 17 A8 04 00", + "000000C0 00 00 E2 24 CB 00 1C F4 AB FD FF FF FF CB 00 38", + "000000D0 E8 57 FB FF FF FF CB 00 54 DC 03 F9 FF FF FF CB", + "000000E0 00 70 D0 AF F6 FF FF FF E2 24 CB 00 E4 0B 54 02", + "000000F0 00 00 00 CB 00 C8 17 A8 04 00 00 00 CB 00 AC 23", + "00000100 FC 06 00 00 00 CB 00 90 2F 50 09 00 00 00 E2 24", + "00000110 CB 00 54 DC 03 F9 FF FF FF CB 00 38 E8 57 FB FF", + "00000120 FF FF CB 00 1C F4 AB FD FF FF FF CB 00 E4 0B 54", + "00000130 02 00 00 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 DB 04 08 00 54 DC 03 F9 FF FF FF 00 38", + "00000010 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000020 0B 54 02 00 00 00 00 E4 0B 54 02 00 00 00 00 C8", + "00000030 17 A8 04 00 00 00 00 AC 23 FC 06 00 00 00 00 90", + "00000040 2F 50 09 00 00 00 00 1C F4 AB FD FF FF FF 00 38", + "00000050 E8 57 FB FF FF FF 00 54 DC 03 F9 FF FF FF 00 70", + "00000060 D0 AF F6 FF FF FF 00 20 5F A0 12 00 00 00 00 58", + "00000070 47 F8 0D 00 00 00 00 90 2F 50 09 00 00 00 00 C8", + "00000080 17 A8 04 00 00 00 00 20 5F A0 12 00 00 00 00 58", + "00000090 47 F8 0D 00 00 00 00 90 2F 50 09 00 00 00 00 C8", + "000000A0 17 A8 04 00 00 00 00 1C F4 AB FD FF FF FF 00 38", + "000000B0 E8 57 FB FF FF FF 00 54 DC 03 F9 FF FF FF 00 70", + "000000C0 D0 AF F6 FF FF FF 00 E4 0B 54 02 00 00 00 00 C8", + "000000D0 17 A8 04 00 00 00 00 AC 23 FC 06 00 00 00 00 90", + "000000E0 2F 50 09 00 00 00 00 54 DC 03 F9 FF FF FF 00 38", + "000000F0 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000100 0B 54 02 00 00 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest7() + { + // ------------------------- + // Float32 Number Arrays + // ------------------------- + + float[] values1 = { -3.1f, -2.1f, -1.1f, 1.1f }; + float[] values2 = { 1.01f, 2.01f, 3.01f, 4.01f }; + float[] values3 = { -1.11f, -2.22f, -3.33f, -4.44f }; + float[] values4 = { 8.811f, 6.611f, 4.411f, 2.211f }; + + float[] valuesS1 = { 1.11f, 2.22f }; + float[] valuesS2 = { 2.22f, 3.33f }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 24 CC 00 00 00 C0 CC CC 08 C0 CC 00 00", + "00000010 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1 BF CC", + "00000020 00 00 00 A0 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 CD 04 66 66 46 C0 66 66 06 C0 CD CC 8C", + "00000010 BF CD CC 8C 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858],[-3.0999999046325684", + @",-2.0999999046325684,-1.100000023841858,1.100000023841858]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 4C E2 24 CC 00 00 00 C0 CC CC 08 C0 CC 00", + "00000010 00 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1 BF", + "00000020 CC 00 00 00 A0 99 99 F1 3F E2 24 CC 00 00 00 C0", + "00000030 CC CC 08 C0 CC 00 00 00 C0 CC CC 00 C0 CC 00 00", + "00000040 00 A0 99 99 F1 BF CC 00 00 00 A0 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CD 04 02 66 66 46 C0 66 66 06 C0 CD CC", + "00000010 8C BF CD CC 8C 3F 66 66 46 C0 66 66 06 C0 CD CC", + "00000020 8C BF CD CC 8C 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(valuesS1), + JsonToken.Float32NumberArray(valuesS1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858],[-3.0999999046325684", + @",-2.0999999046325684,-1.100000023841858,1.100000023841858],[1.1100000143051147,2.2200000286102295],[", + @"1.1100000143051147,2.2200000286102295]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 74 E2 24 CC 00 00 00 C0 CC CC 08 C0 CC 00", + "00000010 00 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1 BF", + "00000020 CC 00 00 00 A0 99 99 F1 3F E2 24 CC 00 00 00 C0", + "00000030 CC CC 08 C0 CC 00 00 00 C0 CC CC 00 C0 CC 00 00", + "00000040 00 A0 99 99 F1 BF CC 00 00 00 A0 99 99 F1 3F E2", + "00000050 12 CC 00 00 00 60 8F C2 F1 3F CC 00 00 00 60 8F", + "00000060 C2 01 40 E2 12 CC 00 00 00 60 8F C2 F1 3F CC 00", + "00000070 00 00 60 8F C2 01 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 3C F0 CD 04 66 66 46 C0 66 66 06 C0 CD CC", + "00000010 8C BF CD CC 8C 3F F0 CD 04 66 66 46 C0 66 66 06", + "00000020 C0 CD CC 8C BF CD CC 8C 3F F0 CD 02 7B 14 8E 3F", + "00000030 7B 14 0E 40 F0 CD 02 7B 14 8E 3F 7B 14 0E 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(values2), + JsonToken.Float32NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858],[1.0099999904632568,", + @"2.009999990463257,3.009999990463257,4.010000228881836],[-1.1100000143051147,-2.2200000286102295,-3.3", + @"299999237060547,-4.440000057220459]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 72 E2 24 CC 00 00 00 C0 CC CC 08 C0 CC 00", + "00000010 00 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1 BF", + "00000020 CC 00 00 00 A0 99 99 F1 3F E2 24 CC 00 00 00 C0", + "00000030 F5 28 F0 3F CC 00 00 00 E0 7A 14 00 40 CC 00 00", + "00000040 00 E0 7A 14 08 40 CC 00 00 00 80 3D 0A 10 40 E2", + "00000050 24 CC 00 00 00 60 8F C2 F1 BF CC 00 00 00 60 8F", + "00000060 C2 01 C0 CC 00 00 00 00 D7 A3 0A C0 CC 00 00 00", + "00000070 60 8F C2 11 C0" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CD 04 03 66 66 46 C0 66 66 06 C0 CD CC", + "00000010 8C BF CD CC 8C 3F AE 47 81 3F D7 A3 00 40 D7 A3", + "00000020 40 40 EC 51 80 40 7B 14 8E BF 7B 14 0E C0 B8 1E", + "00000030 55 C0 7B 14 8E C0" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(values2), + JsonToken.Float32NumberArray(values3), + JsonToken.Float32NumberArray(values4), + JsonToken.Float32NumberArray(values4), + JsonToken.Float32NumberArray(values3), + JsonToken.Float32NumberArray(values2), + JsonToken.Float32NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858],[1.0099999904632568,", + @"2.009999990463257,3.009999990463257,4.010000228881836],[-1.1100000143051147,-2.2200000286102295,-3.3", + @"299999237060547,-4.440000057220459],[8.810999870300293,6.611000061035156,4.410999774932861,2.2109999", + @"656677246],[8.810999870300293,6.611000061035156,4.410999774932861,2.2109999656677246],[-1.1100000143", + @"051147,-2.2200000286102295,-3.3299999237060547,-4.440000057220459],[1.0099999904632568,2.00999999046", + @"3257,3.009999990463257,4.010000228881836],[-3.0999999046325684,-2.0999999046325684,-1.10000002384185", + @"8,1.100000023841858]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 30 01 E2 24 CC 00 00 00 C0 CC CC 08 C0 CC", + "00000010 00 00 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1", + "00000020 BF CC 00 00 00 A0 99 99 F1 3F E2 24 CC 00 00 00", + "00000030 C0 F5 28 F0 3F CC 00 00 00 E0 7A 14 00 40 CC 00", + "00000040 00 00 E0 7A 14 08 40 CC 00 00 00 80 3D 0A 10 40", + "00000050 E2 24 CC 00 00 00 60 8F C2 F1 BF CC 00 00 00 60", + "00000060 8F C2 01 C0 CC 00 00 00 00 D7 A3 0A C0 CC 00 00", + "00000070 00 60 8F C2 11 C0 E2 24 CC 00 00 00 60 3B 9F 21", + "00000080 40 CC 00 00 00 00 AA 71 1A 40 CC 00 00 00 20 DD", + "00000090 A4 11 40 CC 00 00 00 C0 20 B0 01 40 E2 24 CC 00", + "000000A0 00 00 60 3B 9F 21 40 CC 00 00 00 00 AA 71 1A 40", + "000000B0 CC 00 00 00 20 DD A4 11 40 CC 00 00 00 C0 20 B0", + "000000C0 01 40 E2 24 CC 00 00 00 60 8F C2 F1 BF CC 00 00", + "000000D0 00 60 8F C2 01 C0 CC 00 00 00 00 D7 A3 0A C0 CC", + "000000E0 00 00 00 60 8F C2 11 C0 E2 24 CC 00 00 00 C0 F5", + "000000F0 28 F0 3F CC 00 00 00 E0 7A 14 00 40 CC 00 00 00", + "00000100 E0 7A 14 08 40 CC 00 00 00 80 3D 0A 10 40 E2 24", + "00000110 CC 00 00 00 C0 CC CC 08 C0 CC 00 00 00 C0 CC CC", + "00000120 00 C0 CC 00 00 00 A0 99 99 F1 BF CC 00 00 00 A0", + "00000130 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CD 04 08 66 66 46 C0 66 66 06 C0 CD CC", + "00000010 8C BF CD CC 8C 3F AE 47 81 3F D7 A3 00 40 D7 A3", + "00000020 40 40 EC 51 80 40 7B 14 8E BF 7B 14 0E C0 B8 1E", + "00000030 55 C0 7B 14 8E C0 DB F9 0C 41 50 8D D3 40 E9 26", + "00000040 8D 40 06 81 0D 40 DB F9 0C 41 50 8D D3 40 E9 26", + "00000050 8D 40 06 81 0D 40 7B 14 8E BF 7B 14 0E C0 B8 1E", + "00000060 55 C0 7B 14 8E C0 AE 47 81 3F D7 A3 00 40 D7 A3", + "00000070 40 40 EC 51 80 40 66 66 46 C0 66 66 06 C0 CD CC", + "00000080 8C BF CD CC 8C 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 6 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(valuesS1), + JsonToken.Float32NumberArray(valuesS2), + JsonToken.Float32NumberArray(values2), + JsonToken.Float32NumberArray(values1), + JsonToken.Float32NumberArray(values2), + JsonToken.Float32NumberArray(valuesS1), + JsonToken.Float32NumberArray(valuesS2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100000023841858],[1.1100000143051147,", + @"2.2200000286102295],[2.2200000286102295,3.3299999237060547],[1.0099999904632568,2.009999990463257,3.", + @"009999990463257,4.010000228881836],[-3.0999999046325684,-2.0999999046325684,-1.100000023841858,1.100", + @"000023841858],[1.0099999904632568,2.009999990463257,3.009999990463257,4.010000228881836],[1.11000001", + @"43051147,2.2200000286102295],[2.2200000286102295,3.3299999237060547]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 E8 E2 24 CC 00 00 00 C0 CC CC 08 C0 CC 00", + "00000010 00 00 C0 CC CC 00 C0 CC 00 00 00 A0 99 99 F1 BF", + "00000020 CC 00 00 00 A0 99 99 F1 3F E2 12 CC 00 00 00 60", + "00000030 8F C2 F1 3F CC 00 00 00 60 8F C2 01 40 E2 12 CC", + "00000040 00 00 00 60 8F C2 01 40 CC 00 00 00 00 D7 A3 0A", + "00000050 40 E2 24 CC 00 00 00 C0 F5 28 F0 3F CC 00 00 00", + "00000060 E0 7A 14 00 40 CC 00 00 00 E0 7A 14 08 40 CC 00", + "00000070 00 00 80 3D 0A 10 40 E2 24 CC 00 00 00 C0 CC CC", + "00000080 08 C0 CC 00 00 00 C0 CC CC 00 C0 CC 00 00 00 A0", + "00000090 99 99 F1 BF CC 00 00 00 A0 99 99 F1 3F E2 24 CC", + "000000A0 00 00 00 C0 F5 28 F0 3F CC 00 00 00 E0 7A 14 00", + "000000B0 40 CC 00 00 00 E0 7A 14 08 40 CC 00 00 00 80 3D", + "000000C0 0A 10 40 E2 12 CC 00 00 00 60 8F C2 F1 3F CC 00", + "000000D0 00 00 60 8F C2 01 40 E2 12 CC 00 00 00 60 8F C2", + "000000E0 01 40 CC 00 00 00 00 D7 A3 0A 40", + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 78 F0 CD 04 66 66 46 C0 66 66 06 C0 CD CC", + "00000010 8C BF CD CC 8C 3F F0 CD 02 7B 14 8E 3F 7B 14 0E", + "00000020 40 F0 CD 02 7B 14 0E 40 B8 1E 55 40 F0 CD 04 AE", + "00000030 47 81 3F D7 A3 00 40 D7 A3 40 40 EC 51 80 40 F0", + "00000040 CD 04 66 66 46 C0 66 66 06 C0 CD CC 8C BF CD CC", + "00000050 8C 3F F0 CD 04 AE 47 81 3F D7 A3 00 40 D7 A3 40", + "00000060 40 EC 51 80 40 F0 CD 02 7B 14 8E 3F 7B 14 0E 40", + "00000070 F0 CD 02 7B 14 0E 40 B8 1E 55 40", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest8() + { + // ------------------------- + // Float64 Number Arrays + // ------------------------- + + double[] values1 = { -3.1, -2.1, -1.1, 1.1 }; + double[] values2 = { 1.01, 2.01, 3.01, 4.01 }; + double[] values3 = { -1.11, -2.22, -3.33, -4.44 }; + double[] values4 = { 8.81, 6.61, 4.41, 2.21 }; + + double[] valuesS1 = { 1.11, 2.22 }; + double[] valuesS2 = { 2.22, 3.33 }; + double[] valuesS3 = { 3.33, 4.44 }; + double[] valuesS4 = { 4.44, 5.55 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E1 E2 24 CC CD CC CC CC CC CC 08 C0 CC CD CC", + "00000010 CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF CC", + "00000020 9A 99 99 99 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 E1 F0 CE 04 CD CC CC CC CC CC 08 C0 CD CC CC", + "00000010 CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99 99", + "00000020 99 99 99 F1 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(values1), + JsonToken.Float64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1],[-3.1,-2.1,-1.1,1.1]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 4C E2 24 CC CD CC CC CC CC CC 08 C0 CC CD", + "00000010 CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF", + "00000020 CC 9A 99 99 99 99 99 F1 3F E2 24 CC CD CC CC CC", + "00000030 CC CC 08 C0 CC CD CC CC CC CC CC 00 C0 CC 9A 99", + "00000040 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CE 04 02 CD CC CC CC CC CC 08 C0 CD CC", + "00000010 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000020 99 99 99 99 F1 3F CD CC CC CC CC CC 08 C0 CD CC", + "00000030 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000040 99 99 99 99 F1 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(values1), + JsonToken.Float64NumberArray(values1), + JsonToken.Float64NumberArray(valuesS1), + JsonToken.Float64NumberArray(valuesS1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1],[-3.1,-2.1,-1.1,1.1],[1.11,2.22],[1.11,2.22]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 74 E2 24 CC CD CC CC CC CC CC 08 C0 CC CD", + "00000010 CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF", + "00000020 CC 9A 99 99 99 99 99 F1 3F E2 24 CC CD CC CC CC", + "00000030 CC CC 08 C0 CC CD CC CC CC CC CC 00 C0 CC 9A 99", + "00000040 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F E2", + "00000050 12 CC C3 F5 28 5C 8F C2 F1 3F CC C3 F5 28 5C 8F", + "00000060 C2 01 40 E2 12 CC C3 F5 28 5C 8F C2 F1 3F CC C3", + "00000070 F5 28 5C 8F C2 01 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 6C F0 CE 04 CD CC CC CC CC CC 08 C0 CD CC", + "00000010 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000020 99 99 99 99 F1 3F F0 CE 04 CD CC CC CC CC CC 08", + "00000030 C0 CD CC CC CC CC CC 00 C0 9A 99 99 99 99 99 F1", + "00000040 BF 9A 99 99 99 99 99 F1 3F F0 CE 02 C3 F5 28 5C", + "00000050 8F C2 F1 3F C3 F5 28 5C 8F C2 01 40 F0 CE 02 C3", + "00000060 F5 28 5C 8F C2 F1 3F C3 F5 28 5C 8F C2 01 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(values1), + JsonToken.Float64NumberArray(values2), + JsonToken.Float64NumberArray(values3), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1],[1.01,2.01,3.01,4.01],[-1.11,-2.22,-3.33,-4.44]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 72 E2 24 CC CD CC CC CC CC CC 08 C0 CC CD", + "00000010 CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF", + "00000020 CC 9A 99 99 99 99 99 F1 3F E2 24 CC 29 5C 8F C2", + "00000030 F5 28 F0 3F CC 14 AE 47 E1 7A 14 00 40 CC 14 AE", + "00000040 47 E1 7A 14 08 40 CC 0A D7 A3 70 3D 0A 10 40 E2", + "00000050 24 CC C3 F5 28 5C 8F C2 F1 BF CC C3 F5 28 5C 8F", + "00000060 C2 01 C0 CC A4 70 3D 0A D7 A3 0A C0 CC C3 F5 28", + "00000070 5C 8F C2 11 C0" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CE 04 03 CD CC CC CC CC CC 08 C0 CD CC", + "00000010 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000020 99 99 99 99 F1 3F 29 5C 8F C2 F5 28 F0 3F 14 AE", + "00000030 47 E1 7A 14 00 40 14 AE 47 E1 7A 14 08 40 0A D7", + "00000040 A3 70 3D 0A 10 40 C3 F5 28 5C 8F C2 F1 BF C3 F5", + "00000050 28 5C 8F C2 01 C0 A4 70 3D 0A D7 A3 0A C0 C3 F5", + "00000060 28 5C 8F C2 11 C0" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(values1), + JsonToken.Float64NumberArray(values2), + JsonToken.Float64NumberArray(values3), + JsonToken.Float64NumberArray(values4), + JsonToken.Float64NumberArray(values4), + JsonToken.Float64NumberArray(values3), + JsonToken.Float64NumberArray(values2), + JsonToken.Float64NumberArray(values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1],[1.01,2.01,3.01,4.01],[-1.11,-2.22,-3.33,-4.44],[8.81,6.61,4.41,2.21],[8.81,6.", + @"61,4.41,2.21],[-1.11,-2.22,-3.33,-4.44],[1.01,2.01,3.01,4.01],[-3.1,-2.1,-1.1,1.1]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E3 30 01 E2 24 CC CD CC CC CC CC CC 08 C0 CC", + "00000010 CD CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1", + "00000020 BF CC 9A 99 99 99 99 99 F1 3F E2 24 CC 29 5C 8F", + "00000030 C2 F5 28 F0 3F CC 14 AE 47 E1 7A 14 00 40 CC 14", + "00000040 AE 47 E1 7A 14 08 40 CC 0A D7 A3 70 3D 0A 10 40", + "00000050 E2 24 CC C3 F5 28 5C 8F C2 F1 BF CC C3 F5 28 5C", + "00000060 8F C2 01 C0 CC A4 70 3D 0A D7 A3 0A C0 CC C3 F5", + "00000070 28 5C 8F C2 11 C0 E2 24 CC 1F 85 EB 51 B8 9E 21", + "00000080 40 CC 71 3D 0A D7 A3 70 1A 40 CC A4 70 3D 0A D7", + "00000090 A3 11 40 CC AE 47 E1 7A 14 AE 01 40 E2 24 CC 1F", + "000000A0 85 EB 51 B8 9E 21 40 CC 71 3D 0A D7 A3 70 1A 40", + "000000B0 CC A4 70 3D 0A D7 A3 11 40 CC AE 47 E1 7A 14 AE", + "000000C0 01 40 E2 24 CC C3 F5 28 5C 8F C2 F1 BF CC C3 F5", + "000000D0 28 5C 8F C2 01 C0 CC A4 70 3D 0A D7 A3 0A C0 CC", + "000000E0 C3 F5 28 5C 8F C2 11 C0 E2 24 CC 29 5C 8F C2 F5", + "000000F0 28 F0 3F CC 14 AE 47 E1 7A 14 00 40 CC 14 AE 47", + "00000100 E1 7A 14 08 40 CC 0A D7 A3 70 3D 0A 10 40 E2 24", + "00000110 CC CD CC CC CC CC CC 08 C0 CC CD CC CC CC CC CC", + "00000120 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99 99 99", + "00000130 99 99 F1 3F" + }; + + string[] expectedBinary2 = + { + "00000000 80 F2 F0 CE 04 08 CD CC CC CC CC CC 08 C0 CD CC", + "00000010 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000020 99 99 99 99 F1 3F 29 5C 8F C2 F5 28 F0 3F 14 AE", + "00000030 47 E1 7A 14 00 40 14 AE 47 E1 7A 14 08 40 0A D7", + "00000040 A3 70 3D 0A 10 40 C3 F5 28 5C 8F C2 F1 BF C3 F5", + "00000050 28 5C 8F C2 01 C0 A4 70 3D 0A D7 A3 0A C0 C3 F5", + "00000060 28 5C 8F C2 11 C0 1F 85 EB 51 B8 9E 21 40 71 3D", + "00000070 0A D7 A3 70 1A 40 A4 70 3D 0A D7 A3 11 40 AE 47", + "00000080 E1 7A 14 AE 01 40 1F 85 EB 51 B8 9E 21 40 71 3D", + "00000090 0A D7 A3 70 1A 40 A4 70 3D 0A D7 A3 11 40 AE 47", + "000000A0 E1 7A 14 AE 01 40 C3 F5 28 5C 8F C2 F1 BF C3 F5", + "000000B0 28 5C 8F C2 01 C0 A4 70 3D 0A D7 A3 0A C0 C3 F5", + "000000C0 28 5C 8F C2 11 C0 29 5C 8F C2 F5 28 F0 3F 14 AE", + "000000D0 47 E1 7A 14 00 40 14 AE 47 E1 7A 14 08 40 0A D7", + "000000E0 A3 70 3D 0A 10 40 CD CC CC CC CC CC 08 C0 CD CC", + "000000F0 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000100 99 99 99 99 F1 3F" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 6 + { + double[][] valueSets = { valuesS1, valuesS2, valuesS3, valuesS4 }; + + JsonToken[] tokensToWrite = new JsonToken[1 + 260 + 1]; + + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int i = 0; i < tokensToWrite.Length - 2; i++) + { + tokensToWrite[1 + i] = JsonToken.Float64NumberArray(valueSets[i % valueSets.Length]); + } + tokensToWrite[^1] = JsonToken.ArrayEnd(); + + string[] expectedText = + { + @"[[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.", + @"11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2", + @".22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22]", + @",[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.", + @"22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3", + @".33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33]", + @",[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.", + @"33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4", + @".44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44]", + @",[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.", + @"44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5", + @".55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55]", + @",[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.", + @"11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2", + @".22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22]", + @",[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.", + @"22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3", + @".33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33]", + @",[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.", + @"33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4", + @".44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44]", + @",[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.", + @"44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5", + @".55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55]", + @",[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.", + @"11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2", + @".22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22]", + @",[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.", + @"22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3", + @".33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33]", + @",[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.33,4.44],[4.44,5.55],[1.11,2.22],[2.22,3.33],[3.", + @"33,4.44],[4.44,5.55]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E6 50 14 04 01 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000010 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000020 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000030 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000040 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000050 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000060 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000070 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000080 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000090 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000000A0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000000B0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000000C0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000000D0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000000E0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000000F0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000100 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000110 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000120 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000130 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000140 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000150 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000160 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000170 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000180 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000190 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000001A0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000001B0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000001C0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000001D0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000001E0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000001F0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000200 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000210 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000220 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000230 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000240 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000250 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000260 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000270 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000280 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000290 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000002A0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000002B0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000002C0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000002D0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000002E0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000002F0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000300 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000310 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000320 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000330 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000340 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000350 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000360 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000370 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000380 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000390 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000003A0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000003B0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000003C0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000003D0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000003E0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000003F0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000400 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000410 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000420 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000430 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000440 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000450 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000460 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000470 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000480 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000490 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000004A0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000004B0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000004C0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000004D0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000004E0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000004F0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000500 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000510 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000520 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000530 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000540 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000550 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000560 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000570 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000580 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000590 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000005A0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000005B0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000005C0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000005D0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000005E0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000005F0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000600 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000610 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000620 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000630 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000640 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000650 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000660 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000670 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000680 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000690 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000006A0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000006B0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000006C0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000006D0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000006E0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000006F0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000700 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000710 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000720 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000730 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000740 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000750 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000760 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000770 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000780 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000790 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000007A0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000007B0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000007C0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000007D0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000007E0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000007F0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000800 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000810 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000820 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000830 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000840 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000850 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000860 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000870 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000880 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000890 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000008A0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000008B0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000008C0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000008D0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000008E0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000008F0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000900 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000910 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000920 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000930 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000940 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000950 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000960 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000970 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000980 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000990 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000009A0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000009B0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000009C0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000009D0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000009E0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000009F0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000A00 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000A10 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000A20 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000A30 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000A40 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000A50 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000A60 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000A70 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000A80 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000A90 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000AA0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000AB0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000AC0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000AD0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000AE0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000AF0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000B00 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000B10 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000B20 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000B30 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000B40 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000B50 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000B60 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000B70 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000B80 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000B90 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000BA0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000BB0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000BC0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000BD0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000BE0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000BF0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000C00 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000C10 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000C20 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000C30 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000C40 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000C50 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000C60 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000C70 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000C80 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000C90 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000CA0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000CB0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000CC0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000CD0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000CE0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000CF0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000D00 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000D10 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000D20 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000D30 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000D40 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000D50 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000D60 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000D70 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000D80 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000D90 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000DA0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000DB0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000DC0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000DD0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000DE0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000DF0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000E00 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000E10 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000E20 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000E30 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000E40 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000E50 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000E60 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000E70 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000E80 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000E90 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000EA0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000EB0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000EC0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000ED0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000EE0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000EF0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000F00 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000F10 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000F20 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000F30 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000F40 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000F50 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000F60 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000F70 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000F80 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000F90 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000FA0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00000FB0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00000FC0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00000FD0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00000FE0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00000FF0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001000 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001010 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001020 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001030 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001040 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001050 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001060 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001070 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001080 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001090 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000010A0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000010B0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000010C0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000010D0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000010E0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000010F0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001100 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001110 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001120 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001130 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001140 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001150 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001160 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001170 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001180 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001190 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000011A0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000011B0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000011C0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000011D0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000011E0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000011F0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001200 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001210 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001220 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001230 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001240 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001250 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001260 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001270 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001280 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001290 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000012A0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000012B0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000012C0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000012D0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000012E0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000012F0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001300 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001310 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001320 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001330 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001340 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001350 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001360 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001370 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001380 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001390 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000013A0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "000013B0 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "000013C0 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "000013D0 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "000013E0 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "000013F0 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001400 33 33 33 33 16 40 E2 12 CC C3 F5 28 5C 8F C2 F1", + "00001410 3F CC C3 F5 28 5C 8F C2 01 40 E2 12 CC C3 F5 28", + "00001420 5C 8F C2 01 40 CC A4 70 3D 0A D7 A3 0A 40 E2 12", + "00001430 CC A4 70 3D 0A D7 A3 0A 40 CC C3 F5 28 5C 8F C2", + "00001440 11 40 E2 12 CC C3 F5 28 5C 8F C2 11 40 CC 33 33", + "00001450 33 33 33 33 16 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 F3 F1 CE 02 00 04 01 C3 F5 28 5C 8F C2 F1 3F", + "00000010 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000020 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000030 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000040 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000050 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000060 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000070 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000080 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000090 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000000A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000000B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000000C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000000D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000000E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000000F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000100 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000110 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000120 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000130 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000140 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000150 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000160 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000170 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000180 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000190 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000001A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000001B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000001C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000001D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000001E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000001F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000200 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000210 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000220 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000230 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000240 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000250 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000260 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000270 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000280 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000290 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000002A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000002B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000002C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000002D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000002E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000002F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000300 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000310 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000320 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000330 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000340 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000350 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000360 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000370 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000380 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000390 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000003A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000003B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000003C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000003D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000003E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000003F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000400 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000410 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000420 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000430 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000440 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000450 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000460 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000470 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000480 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000490 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000004A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000004B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000004C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000004D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000004E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000004F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000500 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000510 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000520 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000530 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000540 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000550 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000560 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000570 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000580 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000590 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000005A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000005B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000005C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000005D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000005E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000005F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000600 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000610 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000620 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000630 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000640 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000650 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000660 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000670 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000680 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000690 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000006A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000006B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000006C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000006D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000006E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000006F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000700 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000710 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000720 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000730 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000740 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000750 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000760 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000770 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000780 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000790 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000007A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000007B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000007C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000007D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000007E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000007F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000800 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000810 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000820 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000830 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000840 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000850 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000860 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000870 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000880 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000890 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000008A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000008B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000008C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000008D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000008E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000008F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000900 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000910 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000920 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000930 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000940 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000950 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000960 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000970 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000980 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000990 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000009A0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000009B0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "000009C0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "000009D0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "000009E0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "000009F0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000A00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000A10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000A20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000A30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000A40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000A50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000A60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000A70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000A80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000A90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000AA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000AB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000AC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000AD0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000AE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000AF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000B00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000B10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000B20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000B30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000B40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000B50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000B60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000B70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000B80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000B90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000BA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000BB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000BC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000BD0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000BE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000BF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000C00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000C10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000C20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000C30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000C40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000C50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000C60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000C70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000C80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000C90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000CA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000CB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000CC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000CD0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000CE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000CF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000D00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000D10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000D20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000D30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000D40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000D50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000D60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000D70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000D80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000D90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000DA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000DB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000DC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000DD0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000DE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000DF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000E00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000E10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000E20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000E30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000E40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000E50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000E60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000E70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000E80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000E90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000EA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000EB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000EC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000ED0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000EE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000EF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000F00 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000F10 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000F20 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000F30 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000F40 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000F50 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000F60 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000F70 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000F80 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000F90 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000FA0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000FB0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00000FC0 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00000FD0 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00000FE0 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00000FF0 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00001000 33 33 33 33 33 33 16 40 C3 F5 28 5C 8F C2 F1 3F", + "00001010 C3 F5 28 5C 8F C2 01 40 C3 F5 28 5C 8F C2 01 40", + "00001020 A4 70 3D 0A D7 A3 0A 40 A4 70 3D 0A D7 A3 0A 40", + "00001030 C3 F5 28 5C 8F C2 11 40 C3 F5 28 5C 8F C2 11 40", + "00001040 33 33 33 33 33 33 16 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest9() + { + // ------------------------- + // Same numeric type/Different sizes + // ------------------------- + + // Common set of number arrays for the tests to follow + sbyte[] i8Values1 = { -100, -50, 50, 100 }; + sbyte[] i8Values2 = { -125, -100, -50, 50, 100, 125 }; + + short[] i16Values1 = { -2000, -1000, 1000, 2000 }; + short[] i16Values2 = { -2500, -2000, -1000, 1000, 2000, 2500 }; + + int[] i32Values1 = { -200000, -100000, 100000, 200000 }; + int[] i32Values2 = { -250000, -200000, -100000, 100000, 200000, 250000 }; + + long[] i64Values1 = { -20000000000, -10000000000, 10000000000, 20000000000 }; + long[] i64Values2 = { -25000000000, -20000000000, -10000000000, 10000000000, 20000000000, 25000000000 }; + + double[] f64Values1 = { -2.1, -1.1, 1.1, 2.1 }; + double[] f64Values2 = { -3.1, -2.1, -1.1, 1.1, 2.1, 3.1 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-100,-50,50,100],[-100,-50,50,100],[-100,-50,50,100],[-125,-100,-50,50,100,125]]" + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 35 E2 0A C9 9C FF C9 CE FF C8 32 C8 64 E2", + "00000010 0A C9 9C FF C9 CE FF C8 32 C8 64 E2 0A C9 9C FF", + "00000020 C9 CE FF C8 32 C8 64 E2 0F C9 83 FF C9 9C FF C9", + "00000030 CE FF C8 32 C8 64 C8 7D" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 1E F0 D8 04 9C CE 32 64 F0 D8 04 9C CE 32", + "00000010 64 F0 D8 04 9C CE 32 64 F0 D8 06 83 9C CE 32 64", + "00000020 7D" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(i16Values1), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2000,-1000,1000,2000],[-2500,-2000,-1000,1000,2000,2500],[-2500,-2000,-1000,1000,2000,2500],[-250", + @"0,-2000,-1000,1000,2000,2500]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 4A E2 0C C9 30 F8 C9 18 FC C9 E8 03 C9 D0", + "00000010 07 E2 12 C9 3C F6 C9 30 F8 C9 18 FC C9 E8 03 C9", + "00000020 D0 07 C9 C4 09 E2 12 C9 3C F6 C9 30 F8 C9 18 FC", + "00000030 C9 E8 03 C9 D0 07 C9 C4 09 E2 12 C9 3C F6 C9 30", + "00000040 F8 C9 18 FC C9 E8 03 C9 D0 07 C9 C4 09" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 38 F0 D9 04 30 F8 18 FC E8 03 D0 07 F0 D9", + "00000010 06 3C F6 30 F8 18 FC E8 03 D0 07 C4 09 F0 D9 06", + "00000020 3C F6 30 F8 18 FC E8 03 D0 07 C4 09 F0 D9 06 3C", + "00000030 F6 30 F8 18 FC E8 03 D0 07 C4 09" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(i32Values1), + JsonToken.Int32NumberArray(i32Values2), + JsonToken.Int32NumberArray(i32Values1), + JsonToken.Int32NumberArray(i32Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-200000,-100000,100000,200000],[-250000,-200000,-100000,100000,200000,250000],[-200000,-100000,100", + @"000,200000],[-250000,-200000,-100000,100000,200000,250000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 6C E2 14 CA C0 F2 FC FF CA 60 79 FE FF CA", + "00000010 A0 86 01 00 CA 40 0D 03 00 E2 1E CA 70 2F FC FF", + "00000020 CA C0 F2 FC FF CA 60 79 FE FF CA A0 86 01 00 CA", + "00000030 40 0D 03 00 CA 90 D0 03 00 E2 14 CA C0 F2 FC FF", + "00000040 CA 60 79 FE FF CA A0 86 01 00 CA 40 0D 03 00 E2", + "00000050 1E CA 70 2F FC FF CA C0 F2 FC FF CA 60 79 FE FF", + "00000060 CA A0 86 01 00 CA 40 0D 03 00 CA 90 D0 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 5C F0 DA 04 C0 F2 FC FF 60 79 FE FF A0 86", + "00000010 01 00 40 0D 03 00 F0 DA 06 70 2F FC FF C0 F2 FC", + "00000020 FF 60 79 FE FF A0 86 01 00 40 0D 03 00 90 D0 03", + "00000030 00 F0 DA 04 C0 F2 FC FF 60 79 FE FF A0 86 01 00", + "00000040 40 0D 03 00 F0 DA 06 70 2F FC FF C0 F2 FC FF 60", + "00000050 79 FE FF A0 86 01 00 40 0D 03 00 90 D0 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(i64Values1), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-20000000000,-10000000000,10000000000,20000000000],[-25000000000,-20000000000,-10000000000,1000000", + @"0000,20000000000,25000000000],[-25000000000,-20000000000,-10000000000,10000000000,20000000000,250000", + @"00000],[-25000000000,-20000000000,-10000000000,10000000000,20000000000,25000000000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 CE E2 24 CB 00 38 E8 57 FB FF FF FF CB 00", + "00000010 1C F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00 00", + "00000020 CB 00 C8 17 A8 04 00 00 00 E2 36 CB 00 46 E2 2D", + "00000030 FA FF FF FF CB 00 38 E8 57 FB FF FF FF CB 00 1C", + "00000040 F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00 00 CB", + "00000050 00 C8 17 A8 04 00 00 00 CB 00 BA 1D D2 05 00 00", + "00000060 00 E2 36 CB 00 46 E2 2D FA FF FF FF CB 00 38 E8", + "00000070 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF CB 00", + "00000080 E4 0B 54 02 00 00 00 CB 00 C8 17 A8 04 00 00 00", + "00000090 CB 00 BA 1D D2 05 00 00 00 E2 36 CB 00 46 E2 2D", + "000000A0 FA FF FF FF CB 00 38 E8 57 FB FF FF FF CB 00 1C", + "000000B0 F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00 00 CB", + "000000C0 00 C8 17 A8 04 00 00 00 CB 00 BA 1D D2 05 00 00", + "000000D0 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 BC F0 DB 04 00 38 E8 57 FB FF FF FF 00 1C", + "00000010 F4 AB FD FF FF FF 00 E4 0B 54 02 00 00 00 00 C8", + "00000020 17 A8 04 00 00 00 F0 DB 06 00 46 E2 2D FA FF FF", + "00000030 FF 00 38 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF", + "00000040 FF 00 E4 0B 54 02 00 00 00 00 C8 17 A8 04 00 00", + "00000050 00 00 BA 1D D2 05 00 00 00 F0 DB 06 00 46 E2 2D", + "00000060 FA FF FF FF 00 38 E8 57 FB FF FF FF 00 1C F4 AB", + "00000070 FD FF FF FF 00 E4 0B 54 02 00 00 00 00 C8 17 A8", + "00000080 04 00 00 00 00 BA 1D D2 05 00 00 00 F0 DB 06 00", + "00000090 46 E2 2D FA FF FF FF 00 38 E8 57 FB FF FF FF 00", + "000000A0 1C F4 AB FD FF FF FF 00 E4 0B 54 02 00 00 00 00", + "000000B0 C8 17 A8 04 00 00 00 00 BA 1D D2 05 00 00 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 5 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values2), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2.1,-1.1,1.1,2.1],[-2.1,-1.1,1.1,2.1],[-3.1,-2.1,-1.1,1.1,2.1,3.1],[-2.1,-1.1,1.1,2.1]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 AA E2 24 CC CD CC CC CC CC CC 00 C0 CC 9A", + "00000010 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F", + "00000020 CC CD CC CC CC CC CC 00 40 E2 24 CC CD CC CC CC", + "00000030 CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99", + "00000040 99 99 99 99 F1 3F CC CD CC CC CC CC CC 00 40 E2", + "00000050 36 CC CD CC CC CC CC CC 08 C0 CC CD CC CC CC CC", + "00000060 CC 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99 99", + "00000070 99 99 99 F1 3F CC CD CC CC CC CC CC 00 40 CC CD", + "00000080 CC CC CC CC CC 08 40 E2 24 CC CD CC CC CC CC CC", + "00000090 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99 99 99", + "000000A0 99 99 F1 3F CC CD CC CC CC CC CC 00 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 9C F0 CE 04 CD CC CC CC CC CC 00 C0 9A 99", + "00000010 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD CC", + "00000020 CC CC CC CC 00 40 F0 CE 04 CD CC CC CC CC CC 00", + "00000030 C0 9A 99 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1", + "00000040 3F CD CC CC CC CC CC 00 40 F0 CE 06 CD CC CC CC", + "00000050 CC CC 08 C0 CD CC CC CC CC CC 00 C0 9A 99 99 99", + "00000060 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD CC CC CC", + "00000070 CC CC 00 40 CD CC CC CC CC CC 08 40 F0 CE 04 CD", + "00000080 CC CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A", + "00000090 99 99 99 99 99 F1 3F CD CC CC CC CC CC 00 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest10() + { + // ------------------------- + // Different numeric types/Same size + // ------------------------- + + // Common set of number arrays for the tests to follow + sbyte[] i8Values1 = { -100, -50, 50, 100 }; + sbyte[] i8Values2 = { -125, -100, -50, 50, 100, 125 }; + + short[] i16Values1 = { -2000, -1000, 1000, 2000 }; + short[] i16Values2 = { -2500, -2000, -1000, 1000, 2000, 2500 }; + + int[] i32Values1 = { -200000, -100000, 100000, 200000 }; + int[] i32Values2 = { -250000, -200000, -100000, 100000, 200000, 250000 }; + + long[] i64Values1 = { -20000000000, -10000000000, 10000000000, 20000000000 }; + long[] i64Values2 = { -25000000000, -20000000000, -10000000000, 10000000000, 20000000000, 25000000000 }; + + double[] f64Values1 = { -2.1, -1.1, 1.1, 2.1 }; + double[] f64Values2 = { -3.1, -2.1, -1.1, 1.1, 2.1, 3.1 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int16NumberArray(i16Values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-100,-50,50,100],[-100,-50,50,100],[-100,-50,50,100],[-2000,-1000,1000,2000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 32 E2 0A C9 9C FF C9 CE FF C8 32 C8 64 E2", + "00000010 0A C9 9C FF C9 CE FF C8 32 C8 64 E2 0A C9 9C FF", + "00000020 C9 CE FF C8 32 C8 64 E2 0C C9 30 F8 C9 18 FC C9", + "00000030 E8 03 C9 D0 07" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 20 F0 D8 04 9C CE 32 64 F0 D8 04 9C CE 32", + "00000010 64 F0 D8 04 9C CE 32 64 F0 D9 04 30 F8 18 FC E8", + "00000020 03 D0 07" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int32NumberArray(i32Values2), + JsonToken.Int32NumberArray(i32Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2500,-2000,-1000,1000,2000,2500],[-2500,-2000,-1000,1000,2000,2500],[-250000,-200000,-100000,1000", + @"00,200000,250000],[-250000,-200000,-100000,100000,200000,250000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 68 E2 12 C9 3C F6 C9 30 F8 C9 18 FC C9 E8", + "00000010 03 C9 D0 07 C9 C4 09 E2 12 C9 3C F6 C9 30 F8 C9", + "00000020 18 FC C9 E8 03 C9 D0 07 C9 C4 09 E2 1E CA 70 2F", + "00000030 FC FF CA C0 F2 FC FF CA 60 79 FE FF CA A0 86 01", + "00000040 00 CA 40 0D 03 00 CA 90 D0 03 00 E2 1E CA 70 2F", + "00000050 FC FF CA C0 F2 FC FF CA 60 79 FE FF CA A0 86 01", + "00000060 00 CA 40 0D 03 00 CA 90 D0 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 54 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07", + "00000010 C4 09 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07 C4", + "00000020 09 F0 DA 06 70 2F FC FF C0 F2 FC FF 60 79 FE FF", + "00000030 A0 86 01 00 40 0D 03 00 90 D0 03 00 F0 DA 06 70", + "00000040 2F FC FF C0 F2 FC FF 60 79 FE FF A0 86 01 00 40", + "00000050 0D 03 00 90 D0 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(f64Values2), + JsonToken.Float64NumberArray(f64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Float64NumberArray(f64Values2), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-3.1,-2.1,-1.1,1.1,2.1,3.1],[-3.1,-2.1,-1.1,1.1,2.1,3.1],[-25000000000,-20000000000,-10000000000,1", + @"0000000000,20000000000,25000000000],[-3.1,-2.1,-1.1,1.1,2.1,3.1]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 E0 E2 36 CC CD CC CC CC CC CC 08 C0 CC CD", + "00000010 CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF", + "00000020 CC 9A 99 99 99 99 99 F1 3F CC CD CC CC CC CC CC", + "00000030 00 40 CC CD CC CC CC CC CC 08 40 E2 36 CC CD CC", + "00000040 CC CC CC CC 08 C0 CC CD CC CC CC CC CC 00 C0 CC", + "00000050 9A 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1", + "00000060 3F CC CD CC CC CC CC CC 00 40 CC CD CC CC CC CC", + "00000070 CC 08 40 E2 36 CB 00 46 E2 2D FA FF FF FF CB 00", + "00000080 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF", + "00000090 CB 00 E4 0B 54 02 00 00 00 CB 00 C8 17 A8 04 00", + "000000A0 00 00 CB 00 BA 1D D2 05 00 00 00 E2 36 CC CD CC", + "000000B0 CC CC CC CC 08 C0 CC CD CC CC CC CC CC 00 C0 CC", + "000000C0 9A 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1", + "000000D0 3F CC CD CC CC CC CC CC 00 40 CC CD CC CC CC CC", + "000000E0 CC 08 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 CC F0 CE 06 CD CC CC CC CC CC 08 C0 CD CC", + "00000010 CC CC CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99", + "00000020 99 99 99 99 F1 3F CD CC CC CC CC CC 00 40 CD CC", + "00000030 CC CC CC CC 08 40 F0 CE 06 CD CC CC CC CC CC 08", + "00000040 C0 CD CC CC CC CC CC 00 C0 9A 99 99 99 99 99 F1", + "00000050 BF 9A 99 99 99 99 99 F1 3F CD CC CC CC CC CC 00", + "00000060 40 CD CC CC CC CC CC 08 40 F0 DB 06 00 46 E2 2D", + "00000070 FA FF FF FF 00 38 E8 57 FB FF FF FF 00 1C F4 AB", + "00000080 FD FF FF FF 00 E4 0B 54 02 00 00 00 00 C8 17 A8", + "00000090 04 00 00 00 00 BA 1D D2 05 00 00 00 F0 CE 06 CD", + "000000A0 CC CC CC CC CC 08 C0 CD CC CC CC CC CC 00 C0 9A", + "000000B0 99 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD", + "000000C0 CC CC CC CC CC 00 40 CD CC CC CC CC CC 08 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Int64NumberArray(i64Values1), + JsonToken.Int64NumberArray(i64Values1), + JsonToken.Int32NumberArray(i32Values1), + JsonToken.Int32NumberArray(i32Values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2.1,-1.1,1.1,2.1],[-2.1,-1.1,1.1,2.1],[-20000000000,-10000000000,10000000000,20000000000],[-20000", + @"000000,-10000000000,10000000000,20000000000],[-200000,-100000,100000,200000],[-200000,-100000,100000", + @",200000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 C4 E2 24 CC CD CC CC CC CC CC 00 C0 CC 9A", + "00000010 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F", + "00000020 CC CD CC CC CC CC CC 00 40 E2 24 CC CD CC CC CC", + "00000030 CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99", + "00000040 99 99 99 99 F1 3F CC CD CC CC CC CC CC 00 40 E2", + "00000050 24 CB 00 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD", + "00000060 FF FF FF CB 00 E4 0B 54 02 00 00 00 CB 00 C8 17", + "00000070 A8 04 00 00 00 E2 24 CB 00 38 E8 57 FB FF FF FF", + "00000080 CB 00 1C F4 AB FD FF FF FF CB 00 E4 0B 54 02 00", + "00000090 00 00 CB 00 C8 17 A8 04 00 00 00 E2 14 CA C0 F2", + "000000A0 FC FF CA 60 79 FE FF CA A0 86 01 00 CA 40 0D 03", + "000000B0 00 E2 14 CA C0 F2 FC FF CA 60 79 FE FF CA A0 86", + "000000C0 01 00 CA 40 0D 03 00" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 B2 F0 CE 04 CD CC CC CC CC CC 00 C0 9A 99", + "00000010 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD CC", + "00000020 CC CC CC CC 00 40 F0 CE 04 CD CC CC CC CC CC 00", + "00000030 C0 9A 99 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1", + "00000040 3F CD CC CC CC CC CC 00 40 F0 DB 04 00 38 E8 57", + "00000050 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4 0B 54", + "00000060 02 00 00 00 00 C8 17 A8 04 00 00 00 F0 DB 04 00", + "00000070 38 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00", + "00000080 E4 0B 54 02 00 00 00 00 C8 17 A8 04 00 00 00 F0", + "00000090 DA 04 C0 F2 FC FF 60 79 FE FF A0 86 01 00 40 0D", + "000000A0 03 00 F0 DA 04 C0 F2 FC FF 60 79 FE FF A0 86 01", + "000000B0 00 40 0D 03 00" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest11() + { + // ------------------------- + // Mixed w/ non-numeric arrays + // ------------------------- + + // Common set of number arrays for the tests to follow + sbyte[] i8Values1 = { -100, -50, 50, 100 }; + sbyte[] i8Values2 = { -125, -100, -50, 50, 100, 125 }; + + short[] i16Values1 = { -2000, -1000, 1000, 2000 }; + short[] i16Values2 = { -2500, -2000, -1000, 1000, 2000, 2500 }; + + int[] i32Values1 = { -200000, -100000, 100000, 200000 }; + int[] i32Values2 = { -250000, -200000, -100000, 100000, 200000, 250000 }; + + long[] i64Values1 = { -20000000000, -10000000000, 10000000000, 20000000000 }; + long[] i64Values2 = { -25000000000, -20000000000, -10000000000, 10000000000, 20000000000, 25000000000 }; + + double[] f64Values1 = { -2.1, -1.1, 1.1, 2.1 }; + double[] f64Values2 = { -3.1, -2.1, -1.1, 1.1, 2.1, 3.1 }; + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.Int8NumberArray(i8Values1), + JsonToken.ArrayStart(), + JsonToken.String("Atlanta"), + JsonToken.String("Dallas"), + JsonToken.String("Seattle"), + JsonToken.ArrayEnd(), + JsonToken.Int16NumberArray(i16Values1), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-100,-50,50,100],[-100,-50,50,100],[-100,-50,50,100],[""Atlanta"",""Dallas"",""Seattle""],[-2000,-1000,1", + @"000,2000]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 4B E2 0A C9 9C FF C9 CE FF C8 32 C8 64 E2", + "00000010 0A C9 9C FF C9 CE FF C8 32 C8 64 E2 0A C9 9C FF", + "00000020 C9 CE FF C8 32 C8 64 E2 17 87 41 74 6C 61 6E 74", + "00000030 61 86 44 61 6C 6C 61 73 87 53 65 61 74 74 6C 65", + "00000040 E2 0C C9 30 F8 C9 18 FC C9 E8 03 C9 D0 07" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 39 F0 D8 04 9C CE 32 64 F0 D8 04 9C CE 32", + "00000010 64 F0 D8 04 9C CE 32 64 E2 17 87 41 74 6C 61 6E", + "00000020 74 61 86 44 61 6C 6C 61 73 87 53 65 61 74 74 6C", + "00000030 65 F0 D9 04 30 F8 18 FC E8 03 D0 07" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 2 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.Int16NumberArray(i16Values2), + JsonToken.ArrayStart(), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.ArrayEnd(), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2500,-2000,-1000,1000,2000,2500],[-2500,-2000,-1000,1000,2000,2500],[-2500,-2000,-1000,1000,2000,", + @"2500],[-2500,-2000,-1000,1000,2000,2500],[false,true]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 54 E2 12 C9 3C F6 C9 30 F8 C9 18 FC C9 E8", + "00000010 03 C9 D0 07 C9 C4 09 E2 12 C9 3C F6 C9 30 F8 C9", + "00000020 18 FC C9 E8 03 C9 D0 07 C9 C4 09 E2 12 C9 3C F6", + "00000030 C9 30 F8 C9 18 FC C9 E8 03 C9 D0 07 C9 C4 09 E2", + "00000040 12 C9 3C F6 C9 30 F8 C9 18 FC C9 E8 03 C9 D0 07", + "00000050 C9 C4 09 E2 02 D1 D2" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 40 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07", + "00000010 C4 09 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07 C4", + "00000020 09 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07 C4 09", + "00000030 F0 D9 06 3C F6 30 F8 18 FC E8 03 D0 07 C4 09 E2", + "00000040 02 D1 D2" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 3 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.Int64NumberArray(i64Values2), + JsonToken.ArrayStart(), + JsonToken.ArrayEnd(), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-25000000000,-20000000000,-10000000000,10000000000,20000000000,25000000000],[-25000000000,-2000000", + @"0000,-10000000000,10000000000,20000000000,25000000000],[-25000000000,-20000000000,-10000000000,10000", + @"000000,20000000000,25000000000],[-25000000000,-20000000000,-10000000000,10000000000,20000000000,2500", + @"0000000],[]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 E1 E2 36 CB 00 46 E2 2D FA FF FF FF CB 00", + "00000010 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF", + "00000020 CB 00 E4 0B 54 02 00 00 00 CB 00 C8 17 A8 04 00", + "00000030 00 00 CB 00 BA 1D D2 05 00 00 00 E2 36 CB 00 46", + "00000040 E2 2D FA FF FF FF CB 00 38 E8 57 FB FF FF FF CB", + "00000050 00 1C F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00", + "00000060 00 CB 00 C8 17 A8 04 00 00 00 CB 00 BA 1D D2 05", + "00000070 00 00 00 E2 36 CB 00 46 E2 2D FA FF FF FF CB 00", + "00000080 38 E8 57 FB FF FF FF CB 00 1C F4 AB FD FF FF FF", + "00000090 CB 00 E4 0B 54 02 00 00 00 CB 00 C8 17 A8 04 00", + "000000A0 00 00 CB 00 BA 1D D2 05 00 00 00 E2 36 CB 00 46", + "000000B0 E2 2D FA FF FF FF CB 00 38 E8 57 FB FF FF FF CB", + "000000C0 00 1C F4 AB FD FF FF FF CB 00 E4 0B 54 02 00 00", + "000000D0 00 CB 00 C8 17 A8 04 00 00 00 CB 00 BA 1D D2 05", + "000000E0 00 00 00 E0" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 CD F0 DB 06 00 46 E2 2D FA FF FF FF 00 38", + "00000010 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF FF 00 E4", + "00000020 0B 54 02 00 00 00 00 C8 17 A8 04 00 00 00 00 BA", + "00000030 1D D2 05 00 00 00 F0 DB 06 00 46 E2 2D FA FF FF", + "00000040 FF 00 38 E8 57 FB FF FF FF 00 1C F4 AB FD FF FF", + "00000050 FF 00 E4 0B 54 02 00 00 00 00 C8 17 A8 04 00 00", + "00000060 00 00 BA 1D D2 05 00 00 00 F0 DB 06 00 46 E2 2D", + "00000070 FA FF FF FF 00 38 E8 57 FB FF FF FF 00 1C F4 AB", + "00000080 FD FF FF FF 00 E4 0B 54 02 00 00 00 00 C8 17 A8", + "00000090 04 00 00 00 00 BA 1D D2 05 00 00 00 F0 DB 06 00", + "000000A0 46 E2 2D FA FF FF FF 00 38 E8 57 FB FF FF FF 00", + "000000B0 1C F4 AB FD FF FF FF 00 E4 0B 54 02 00 00 00 00", + "000000C0 C8 17 A8 04 00 00 00 00 BA 1D D2 05 00 00 00 E0", + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + + // Case 4 + { + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.ArrayStart(), + JsonToken.Int32NumberArray(i32Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.Float64NumberArray(f64Values1), + JsonToken.ArrayEnd(), + JsonToken.ArrayEnd(), + }; + + string[] expectedText = + { + @"[[-2.1,-1.1,1.1,2.1],[-2.1,-1.1,1.1,2.1],[-2.1,-1.1,1.1,2.1],[[-200000,-100000,100000,200000],[-2.1,", + @"-1.1,1.1,2.1],[-2.1,-1.1,1.1,2.1]]]", + }; + + string[] expectedBinary1 = + { + "00000000 80 E2 D6 E2 24 CC CD CC CC CC CC CC 00 C0 CC 9A", + "00000010 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F", + "00000020 CC CD CC CC CC CC CC 00 40 E2 24 CC CD CC CC CC", + "00000030 CC CC 00 C0 CC 9A 99 99 99 99 99 F1 BF CC 9A 99", + "00000040 99 99 99 99 F1 3F CC CD CC CC CC CC CC 00 40 E2", + "00000050 24 CC CD CC CC CC CC CC 00 C0 CC 9A 99 99 99 99", + "00000060 99 F1 BF CC 9A 99 99 99 99 99 F1 3F CC CD CC CC", + "00000070 CC CC CC 00 40 E2 62 E2 14 CA C0 F2 FC FF CA 60", + "00000080 79 FE FF CA A0 86 01 00 CA 40 0D 03 00 E2 24 CC", + "00000090 CD CC CC CC CC CC 00 C0 CC 9A 99 99 99 99 99 F1", + "000000A0 BF CC 9A 99 99 99 99 99 F1 3F CC CD CC CC CC CC", + "000000B0 CC 00 40 E2 24 CC CD CC CC CC CC CC 00 C0 CC 9A", + "000000C0 99 99 99 99 99 F1 BF CC 9A 99 99 99 99 99 F1 3F", + "000000D0 CC CD CC CC CC CC CC 00 40" + }; + + string[] expectedBinary2 = + { + "00000000 80 E2 C4 F0 CE 04 CD CC CC CC CC CC 00 C0 9A 99", + "00000010 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD CC", + "00000020 CC CC CC CC 00 40 F0 CE 04 CD CC CC CC CC CC 00", + "00000030 C0 9A 99 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1", + "00000040 3F CD CC CC CC CC CC 00 40 F0 CE 04 CD CC CC CC", + "00000050 CC CC 00 C0 9A 99 99 99 99 99 F1 BF 9A 99 99 99", + "00000060 99 99 F1 3F CD CC CC CC CC CC 00 40 E2 59 F0 DA", + "00000070 04 C0 F2 FC FF 60 79 FE FF A0 86 01 00 40 0D 03", + "00000080 00 F0 CE 04 CD CC CC CC CC CC 00 C0 9A 99 99 99", + "00000090 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD CC CC CC", + "000000A0 CC CC 00 40 F0 CE 04 CD CC CC CC CC CC 00 C0 9A", + "000000B0 99 99 99 99 99 F1 BF 9A 99 99 99 99 99 F1 3F CD", + "000000C0 CC CC CC CC CC 00 40" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + + [TestMethod] + [Owner("sboshra")] + public void UniformArrayOfNumberArraysTest12() + { + // ------------------------- + // Misc. Reported Issues + // ------------------------- + + // Case 1 + { + JsonToken[] tokensToWrite = + { + JsonToken.ObjectStart(), + JsonToken.FieldName("id"), + JsonToken.String("1da1ac75-b910-4383-927f-c8d09be18500"), + JsonToken.FieldName("mypk"), + JsonToken.String("ea3a2e12-570e-49da-b262-a6b5341fea0c"), + JsonToken.FieldName("sgmts"), + JsonToken.ArrayStart(), + JsonToken.ArrayStart(), + JsonToken.Number(6519456), + JsonToken.Number(1471916863), + JsonToken.ArrayEnd(), + JsonToken.ArrayStart(), + JsonToken.Number(2498434), + JsonToken.Number(1455671440), + JsonToken.ArrayEnd(), + JsonToken.ArrayEnd(), + JsonToken.ObjectEnd(), + }; + + string[] expectedText = + { + @"{""id"":""1da1ac75-b910-4383-927f-c8d09be18500"",""mypk"":""ea3a2e12-570e-49da-b262-a6b5341fea0c"",""sgmts"":[", + @"[6519456,1471916863],[2498434,1455671440]]}", + }; + + string[] expectedBinary1 = + { + "00000000 80 EA 48 2C 75 D1 1A CA 57 9B 01 34 38 29 F7 8C", + "00000010 0D B9 1E 58 00 84 6D 79 70 6B 75 AE A3 E2 21 75", + "00000020 E0 94 AD 2B 26 6A 5B 43 F1 AE C0 85 73 67 6D 74", + "00000030 73 E2 18 E2 0A CA A0 7A 63 00 CA 3F AB BB 57 E2", + "00000040 0A CA 82 1F 26 00 CA 90 C8 C3 56" + }; + + string[] expectedBinary2 = + { + "00000000 80 EA 43 2C 75 D1 1A CA 57 9B 01 34 38 29 F7 8C", + "00000010 0D B9 1E 58 00 84 6D 79 70 6B 75 AE A3 E2 21 75", + "00000020 E0 94 AD 2B 26 6A 5B 43 F1 AE C0 85 73 67 6D 74", + "00000030 73 F2 F0 DA 02 02 A0 7A 63 00 3F AB BB 57 82 1F", + "00000040 26 00 90 C8 C3 56" + }; + + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary1, JsonWriteOptions.None); + ExecuteAndValidate(tokensToWrite, expectedText, expectedBinary2, JsonWriteOptions.EnableNumberArrays); + } + } + #endregion Array + + #region Escaping + [TestMethod] + [Owner("mayapainter")] + public void EscapeCharacterTest() + { + /// + /// Set of all escape characters in JSON. + /// + Tuple[] escapeCharacters = new Tuple[] + { + new Tuple(@"\b", "\b"), + new Tuple(@"\f", "\f"), + new Tuple(@"\n", "\n"), + new Tuple(@"\r", "\r"), + new Tuple(@"\t", "\t"), + new Tuple(@"\""", "\""), + new Tuple(@"\\", @"\"), + }; + + foreach (Tuple escapeCharacter in escapeCharacters) + { + string expectedString = "\"" + escapeCharacter.Item1 + "\""; + + JsonToken[] tokensToWrite = + { + JsonToken.String(escapeCharacter.Item2), + }; + + this.VerifyWriter(tokensToWrite, expectedString); + // Binary does not test this since you would just put the literal character if you wanted it. + } + } + + [TestMethod] + [Owner("mayapainter")] + public void UnicodeEscapeTest() + { + // You don't have to escape a regular unicode character + string expectedString = "\"\x20AC\""; + + JsonToken[] tokensToWrite = + { + JsonToken.String("\x20AC"), + }; + + this.VerifyWriter(tokensToWrite, expectedString); + // Binary does not test this since you would just put the literal character if you wanted it. + } [TestMethod] [Owner("mayapainter")] @@ -2238,7 +7731,6 @@ public void UnicodeTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } [TestMethod] @@ -2262,7 +7754,6 @@ public void EmojiUTF32Test() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } [TestMethod] @@ -2289,6 +7780,7 @@ public void ControlCharacterTests() } } #endregion + #region Objects [TestMethod] [Owner("mayapainter")] @@ -2298,7 +7790,7 @@ public void EmptyObjectTest() byte[] binaryOutput = { BinaryFormat, - JsonBinaryEncoding.TypeMarker.EmptyObject, + JsonBinaryEncoding.TypeMarker.Obj0, }; JsonToken[] tokensToWrite = @@ -2309,7 +7801,6 @@ public void EmptyObjectTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -2327,7 +7818,7 @@ public void SimpleObjectTest() { List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL1 } }; List elements = new List @@ -2348,7 +7839,7 @@ public void SimpleObjectTest() { List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL1 } }; List elements = new List @@ -2377,7 +7868,6 @@ public void SimpleObjectTest() this.VerifyWriter(tokensToWrite, expectedString); this.VerifyWriter(tokensToWrite, binaryOutput); - this.VerifyWriter(tokensToWrite, binaryOutput, null, false); } [TestMethod] @@ -2412,7 +7902,7 @@ public void AllPrimitivesObjectTest() { List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object2ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL2 } }; List elements = new List @@ -2455,11 +7945,11 @@ public void AllPrimitivesObjectTest() }; byte[] innerArrayElementsBytes = innerArrayElements.SelectMany(x => x).ToArray(); - innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Array1ByteLength, (byte)innerArrayElementsBytes.Length }); + innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ArrL1, (byte)innerArrayElementsBytes.Length }); innerObjectElements.Add(innerArrayElementsBytes); byte[] innerObjectElementsBytes = innerObjectElements.SelectMany(x => x).ToArray(); - elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); + elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ObjL1, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "text".Length), 116, 101, 120, 116 }); @@ -2476,7 +7966,7 @@ public void AllPrimitivesObjectTest() { List binaryOutputBuilder = new List { - new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Object1ByteLength } + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.ObjL1 } }; List elements = new List @@ -2519,11 +8009,11 @@ public void AllPrimitivesObjectTest() }; byte[] innerArrayElementsBytes = innerArrayElements.SelectMany(x => x).ToArray(); - innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Array1ByteLength, (byte)innerArrayElementsBytes.Length }); + innerObjectElements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ArrL1, (byte)innerArrayElementsBytes.Length }); innerObjectElements.Add(innerArrayElementsBytes); byte[] innerObjectElementsBytes = innerObjectElements.SelectMany(x => x).ToArray(); - elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); + elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.ObjL1, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 7) }); @@ -2582,6 +8072,7 @@ public void AllPrimitivesObjectTest() this.VerifyWriter(tokensToWrite, binaryOutput); } #endregion + #region Exceptions [TestMethod] [Owner("mayapainter")] @@ -2658,6 +8149,7 @@ public void PropertyAlreadyAddedTest() // Binary does not test this. } #endregion + #region ExtendedTypes [TestMethod] [Owner("mayapainter")] @@ -2685,7 +8177,6 @@ public void Int8Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2715,7 +8206,6 @@ public void Int16Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2745,7 +8235,6 @@ public void Int32Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2775,7 +8264,6 @@ public void Int64Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2805,7 +8293,6 @@ public void UInt32Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2835,7 +8322,6 @@ public void Float32Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2865,7 +8351,6 @@ public void Float64Test() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2895,7 +8380,6 @@ public void GuidTest() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } @@ -2924,7 +8408,6 @@ public void BinaryTest() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } { @@ -2950,7 +8433,6 @@ public void BinaryTest() this.VerifyWriter(tokensToWrite, expectedStringOutput); this.VerifyWriter(tokensToWrite, expectedBinaryOutput); - this.VerifyWriter(tokensToWrite, expectedBinaryOutput, null, false); } } #endregion @@ -2983,7 +8465,7 @@ private void VerifyWriter(JsonToken[] tokensToWrite, string expectedString = nul { System.Threading.Thread.CurrentThread.CurrentCulture = cultureInfo; - // Create through serializtion api + // Create through serialization API IJsonWriter jsonWriter = JsonWriter.Create(JsonSerializationFormat.Text); byte[] expectedOutput = expectedString != null ? Encoding.UTF8.GetBytes(expectedString) : null; this.VerifyWriter( @@ -3002,11 +8484,11 @@ private void VerifyWriter(JsonToken[] tokensToWrite, string expectedString = nul } } - private void VerifyWriter(JsonToken[] tokensToWrite, byte[] binaryOutput, Exception expectedException = null, bool enableEncodedStrings = true) + private void VerifyWriter(JsonToken[] tokensToWrite, byte[] binaryOutput, Exception expectedException = null) { foreach (bool writeAsUtf8String in new bool[] { false, true }) { - IJsonWriter jsonWriter = JsonWriter.Create(JsonSerializationFormat.Binary, 256, enableEncodedStrings); + IJsonWriter jsonWriter = JsonWriter.Create(JsonSerializationFormat.Binary, JsonWriteOptions.None, 256); this.VerifyWriter(jsonWriter, tokensToWrite, binaryOutput, JsonSerializationFormat.Binary, writeAsUtf8String, expectedException); } } @@ -3024,118 +8506,7 @@ private void VerifyWriter( try { - foreach (JsonToken token in tokensToWrite) - { - switch (token.JsonTokenType) - { - case JsonTokenType.BeginArray: - jsonWriter.WriteArrayStart(); - break; - - case JsonTokenType.EndArray: - jsonWriter.WriteArrayEnd(); - break; - - case JsonTokenType.BeginObject: - jsonWriter.WriteObjectStart(); - break; - - case JsonTokenType.EndObject: - jsonWriter.WriteObjectEnd(); - break; - - case JsonTokenType.String: - string stringValue = (token as JsonStringToken).Value; - if (writeAsUtf8String) - { - jsonWriter.WriteStringValue(Utf8Span.TranscodeUtf16(stringValue)); - } - else - { - jsonWriter.WriteStringValue(stringValue); - } - break; - - case JsonTokenType.Number: - Number64 numberValue = (token as JsonNumberToken).Value; - jsonWriter.WriteNumber64Value(numberValue); - break; - - case JsonTokenType.True: - jsonWriter.WriteBoolValue(true); - break; - - case JsonTokenType.False: - jsonWriter.WriteBoolValue(false); - break; - - case JsonTokenType.Null: - jsonWriter.WriteNullValue(); - break; - - case JsonTokenType.FieldName: - string fieldNameValue = (token as JsonFieldNameToken).Value; - if (writeAsUtf8String) - { - jsonWriter.WriteFieldName(Utf8Span.TranscodeUtf16(fieldNameValue)); - } - else - { - jsonWriter.WriteFieldName(fieldNameValue); - } - break; - - case JsonTokenType.Int8: - sbyte int8Value = (token as JsonInt8Token).Value; - jsonWriter.WriteInt8Value(int8Value); - break; - - case JsonTokenType.Int16: - short int16Value = (token as JsonInt16Token).Value; - jsonWriter.WriteInt16Value(int16Value); - break; - - case JsonTokenType.Int32: - int int32Value = (token as JsonInt32Token).Value; - jsonWriter.WriteInt32Value(int32Value); - break; - - case JsonTokenType.Int64: - long int64Value = (token as JsonInt64Token).Value; - jsonWriter.WriteInt64Value(int64Value); - break; - - case JsonTokenType.UInt32: - uint uint32Value = (token as JsonUInt32Token).Value; - jsonWriter.WriteUInt32Value(uint32Value); - break; - - case JsonTokenType.Float32: - float float32Value = (token as JsonFloat32Token).Value; - jsonWriter.WriteFloat32Value(float32Value); - break; - - case JsonTokenType.Float64: - double float64Value = (token as JsonFloat64Token).Value; - jsonWriter.WriteFloat64Value(float64Value); - break; - - case JsonTokenType.Guid: - Guid guidValue = (token as JsonGuidToken).Value; - jsonWriter.WriteGuidValue(guidValue); - break; - - case JsonTokenType.Binary: - ReadOnlyMemory binaryValue = (token as JsonBinaryToken).Value; - jsonWriter.WriteBinaryValue(binaryValue.Span); - break; - - case JsonTokenType.NotStarted: - default: - Assert.Fail(string.Format("Got an unexpected JsonTokenType: {0} as an expected token type", token.JsonTokenType)); - break; - } - } + JsonTestUtils.WriteTokens(tokensToWrite, jsonWriter, writeAsUtf8String); } catch (Exception exception) { @@ -3159,5 +8530,151 @@ private void VerifyWriter( } } } + + private static void ExecuteAndValidate( + JsonToken[] inputTokens, + string[] expectedTextResult, + string[] expectedBinaryResult, + JsonWriteOptions writeOptions, + bool skipRoundTripTest = false) + { + Assert.IsNotNull(inputTokens); + Assert.IsNotNull(expectedTextResult); + Assert.IsNotNull(expectedBinaryResult); + + JsonSerializationFormat[] serializationFormats = new JsonSerializationFormat[] + { + JsonSerializationFormat.Text, + JsonSerializationFormat.Binary + }; + + string[][] exptectedResults = new string[][] + { + expectedTextResult, + expectedBinaryResult + }; + + Assert.AreEqual(serializationFormats.Length, exptectedResults.Length); + + for (int i = 0; i < serializationFormats.Length; i++) + { + JsonSerializationFormat serializationFormat = serializationFormats[i]; + string[] expectedResult = exptectedResults[i]; + + foreach (bool writeAsUtf8String in new bool[] { false, true }) + { + IJsonWriter jsonWriter = JsonWriter.Create(serializationFormat, writeOptions); + JsonTestUtils.WriteTokens(inputTokens, jsonWriter, writeAsUtf8String); + ReadOnlyMemory result = jsonWriter.GetResult(); + + string[] actualResult = JsonTestUtils.SerializeResultBuffer(result.ToArray(), serializationFormat); + if (!VerifyResults(expectedResult, actualResult)) + { + Assert.Fail($"JsonWriter validation failed for format '{serializationFormat}' and write options '{writeOptions}'."); + } + } + } + + if(!skipRoundTripTest) + { + SerializationSpec[] serializationSpecs = new SerializationSpec[] + { + SerializationSpec.Text(JsonWriteOptions.None), + SerializationSpec.Binary(JsonWriteOptions.None), + SerializationSpec.Binary(JsonWriteOptions.EnableNumberArrays), + SerializationSpec.Binary(JsonWriteOptions.EnableUInt64), + }; + + RewriteScenario[] rewriteScenarios = new RewriteScenario[] + { + RewriteScenario.NavigatorRoot, + RewriteScenario.NavigatorNode, + RewriteScenario.ReaderAll, + RewriteScenario.ReaderToken, + }; + + foreach (SerializationSpec inputSpec in serializationSpecs) + { + IJsonWriter inputWriter = JsonWriter.Create(inputSpec.SerializationFormat, inputSpec.WriteOptions); + WriteTokens(inputTokens, inputWriter, writeAsUtf8String: true); + ReadOnlyMemory inputResult = inputWriter.GetResult(); + + foreach (SerializationSpec outputSpec in serializationSpecs) + { + foreach (RewriteScenario rewriteScenario in rewriteScenarios) + { + VerifyJsonRoundTrip( + inputResult, + inputJson: null, + inputSpec, + outputSpec, + rewriteScenario); + } + } + } + } + } + + private static bool VerifyResults( + string[] expectedStringResults, + string[] actualStringResults) + { + Assert.IsNotNull(expectedStringResults); + Assert.IsNotNull(actualStringResults); + + if (expectedStringResults.Length != actualStringResults.Length) + { + DumpExpectedActualResults(expectedStringResults, actualStringResults); + + return false; + } + + for (int i = 0; i < expectedStringResults.Length; i++) + { + if (expectedStringResults[i] != actualStringResults[i]) + { + Console.WriteLine($"Incorrect actual result at line number {i}."); + Console.WriteLine(); + Console.WriteLine("Expected: " + expectedStringResults[i]); + Console.WriteLine("Actual : " + actualStringResults[i]); + + DumpExpectedActualResults(expectedStringResults, actualStringResults); + + return false; + } + } + + return true; + } + + private static void DumpExpectedActualResults( + string[] expectedStringResults, + string[] actualStringResults) + { + Assert.IsNotNull(expectedStringResults); + Assert.IsNotNull(actualStringResults); + + Console.WriteLine(); + Console.WriteLine("Expected Result:"); + foreach (string item in expectedStringResults) + { + Console.WriteLine(item); + } + + Console.WriteLine(); + Console.WriteLine("Actual Result:"); + foreach (string item in actualStringResults) + { + Console.WriteLine(item); + } + } + + static private sbyte[] Int8Array(params sbyte[] values) => values; + static private byte[] UInt8Array(params byte[] values) => values; + static private short[] Int16Array(params short[] values) => values; + static private int[] Int32Array(params int[] values) => values; + static private long[] Int64Array(params long[] values) => values; + static private float[] Float32Array(params float[] values) => values; + static private double[] Float64Array(params double[] values) => values; } } \ No newline at end of file diff --git a/changelog.md b/changelog.md index 041f992f74..30c79faf7b 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,14 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.46.0-preview.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.46.0-preview.2) - 2024-11-12 + +### [3.45.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.45.2) - 2024-11-12 + +#### Added + +- [4866](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4866) JSON Binary Encoding: Adds support for encoding uniform arrays. + ### [3.46.0-preview.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.46.0-preview.1) - 2024-11-06 ### [3.45.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.45.1) - 2024-11-06