Skip to content

Commit 58d847d

Browse files
Merge branch 'master' into users/nalutripician/direct3.38.0Upgrade
2 parents 95f92bb + 1d0046e commit 58d847d

22 files changed

Lines changed: 819 additions & 133 deletions

Microsoft.Azure.Cosmos/src/Json/IJsonBinaryWriterExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ void WriteRawJsonValue(
1212
ReadOnlyMemory<byte> rootBuffer,
1313
int valueOffset,
1414
JsonBinaryEncoding.UniformArrayInfo externalArrayInfo,
15-
bool isFieldName);
15+
bool isFieldName,
16+
IJsonReadOnlyStringDictionary jsonStringDictionary = null);
1617
}
1718
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------
4+
namespace Microsoft.Azure.Cosmos.Json
5+
{
6+
using System;
7+
using Microsoft.Azure.Cosmos.Core.Utf8;
8+
9+
#if INTERNAL
10+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
11+
#pragma warning disable SA1600 // Elements should be documented
12+
public
13+
#else
14+
internal
15+
#endif
16+
interface IJsonReadOnlyStringDictionary : IEquatable<IJsonReadOnlyStringDictionary>
17+
{
18+
bool TryGetString(int stringId, out UtfAllString value);
19+
20+
bool TryGetStringId(Utf8Span value, out int stringId);
21+
22+
public int GetCount();
23+
}
24+
}

Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Strings.cs

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos.Json
1010
using System.Linq;
1111
using System.Runtime.CompilerServices;
1212
using System.Runtime.InteropServices;
13-
using Microsoft.Azure.Cosmos.Core;
1413
using Microsoft.Azure.Cosmos.Core.Utf8;
1514

1615
internal static partial class JsonBinaryEncoding
@@ -175,36 +174,40 @@ internal static partial class JsonBinaryEncoding
175174

176175
public static string GetStringValue(
177176
ReadOnlyMemory<byte> buffer,
178-
ReadOnlyMemory<byte> stringToken)
177+
ReadOnlyMemory<byte> stringToken,
178+
IJsonReadOnlyStringDictionary jsonStringDictionary)
179179
{
180180
// First retrieve the string length
181-
GetStringValue(buffer, stringToken, destinationBuffer: Span<byte>.Empty, out int valueLength);
181+
GetStringValue(buffer, stringToken, jsonStringDictionary, destinationBuffer: Span<byte>.Empty, out int valueLength);
182182

183183
Span<byte> destinationBuffer = valueLength < MaxStackAlloc ? stackalloc byte[valueLength] : new byte[valueLength];
184-
GetStringValue(buffer, stringToken, destinationBuffer, out valueLength);
184+
GetStringValue(buffer, stringToken, jsonStringDictionary, destinationBuffer, out valueLength);
185185

186186
return Utf8Span.UnsafeFromUtf8BytesNoValidation(destinationBuffer).ToString();
187187
}
188188

189189
[MethodImpl(MethodImplOptions.AggressiveInlining)]
190190
public static Utf8Span GetUtf8SpanValue(
191191
ReadOnlyMemory<byte> buffer,
192-
ReadOnlyMemory<byte> stringToken)
192+
ReadOnlyMemory<byte> stringToken,
193+
IJsonReadOnlyStringDictionary jsonStringDictionary)
193194
{
194-
return Utf8Span.UnsafeFromUtf8BytesNoValidation(GetUtf8MemoryValue(buffer, stringToken).Span);
195+
return Utf8Span.UnsafeFromUtf8BytesNoValidation(GetUtf8MemoryValue(buffer, stringToken, jsonStringDictionary).Span);
195196
}
196197

197198
[MethodImpl(MethodImplOptions.AggressiveInlining)]
198199
public static Utf8String GetUtf8StringValue(
199200
ReadOnlyMemory<byte> buffer,
200-
ReadOnlyMemory<byte> stringToken)
201+
ReadOnlyMemory<byte> stringToken,
202+
IJsonReadOnlyStringDictionary jsonStringDictionary)
201203
{
202-
return Utf8String.UnsafeFromUtf8BytesNoValidation(GetUtf8MemoryValue(buffer, stringToken));
204+
return Utf8String.UnsafeFromUtf8BytesNoValidation(GetUtf8MemoryValue(buffer, stringToken, jsonStringDictionary));
203205
}
204206

205207
public static bool TryGetBufferedStringValue(
206208
ReadOnlyMemory<byte> buffer,
207209
ReadOnlyMemory<byte> stringToken,
210+
IJsonReadOnlyStringDictionary jsonStringDictionary,
208211
out Utf8Memory value)
209212
{
210213
if (stringToken.IsEmpty)
@@ -216,13 +219,15 @@ public static bool TryGetBufferedStringValue(
216219
if (JsonBinaryEncoding.TryGetBufferedLengthPrefixedString(
217220
buffer,
218221
stringToken,
222+
jsonStringDictionary,
219223
out value))
220224
{
221225
return true;
222226
}
223227

224228
if (JsonBinaryEncoding.TryGetEncodedStringValue(
225229
stringToken.Span,
230+
jsonStringDictionary,
226231
out UtfAllString encodedStringValue))
227232
{
228233
value = encodedStringValue.Utf8EscapedString;
@@ -235,13 +240,19 @@ public static bool TryGetBufferedStringValue(
235240

236241
public static bool TryGetDictionaryEncodedStringValue(
237242
ReadOnlySpan<byte> stringToken,
238-
out UtfAllString value) => TryGetEncodedStringValue(
243+
IJsonReadOnlyStringDictionary jsonStringDictionary,
244+
out UtfAllString value)
245+
{
246+
return TryGetEncodedStringValue(
239247
stringToken,
248+
jsonStringDictionary,
240249
out value);
250+
}
241251

242252
private static ReadOnlyMemory<byte> GetUtf8MemoryValue(
243253
ReadOnlyMemory<byte> buffer,
244-
ReadOnlyMemory<byte> stringToken)
254+
ReadOnlyMemory<byte> stringToken,
255+
IJsonReadOnlyStringDictionary jsonStringDictionary)
245256
{
246257
byte typeMarker = stringToken.Span[0];
247258

@@ -250,6 +261,7 @@ private static ReadOnlyMemory<byte> GetUtf8MemoryValue(
250261
if (!TryGetBufferedStringValue(
251262
buffer,
252263
stringToken,
264+
jsonStringDictionary,
253265
out Utf8Memory bufferedStringValue))
254266
{
255267
throw new JsonInvalidTokenException();
@@ -272,6 +284,7 @@ private static ReadOnlyMemory<byte> GetUtf8MemoryValue(
272284
private static void GetStringValue(
273285
ReadOnlyMemory<byte> buffer,
274286
ReadOnlyMemory<byte> stringToken,
287+
IJsonReadOnlyStringDictionary jsonStringDictionary,
275288
Span<byte> destinationBuffer,
276289
out int valueLength)
277290
{
@@ -286,6 +299,7 @@ private static void GetStringValue(
286299
if (!TryGetBufferedStringValue(
287300
buffer,
288301
stringToken,
302+
jsonStringDictionary,
289303
out Utf8Memory bufferedStringValue))
290304
{
291305
throw new JsonInvalidTokenException();
@@ -317,18 +331,20 @@ private static void GetStringValue(
317331
/// Try Get Encoded String Value
318332
/// </summary>
319333
/// <param name="stringToken">The string token to read from.</param>
334+
/// <param name="jsonStringDictionary">The JSON string dictionary.</param>
320335
/// <param name="value">The encoded string if found.</param>
321336
/// <returns>Encoded String Value</returns>
322337
private static bool TryGetEncodedStringValue(
323338
ReadOnlySpan<byte> stringToken,
339+
IJsonReadOnlyStringDictionary jsonStringDictionary,
324340
out UtfAllString value)
325341
{
326342
if (JsonBinaryEncoding.TryGetEncodedSystemStringValue(stringToken, out value))
327343
{
328344
return true;
329345
}
330346

331-
if (JsonBinaryEncoding.TryGetEncodedUserStringValue(stringToken, out value))
347+
if (JsonBinaryEncoding.TryGetEncodedUserStringValue(stringToken, jsonStringDictionary, out value))
332348
{
333349
return true;
334350
}
@@ -367,14 +383,22 @@ private static bool TryGetEncodedSystemStringValue(
367383
/// Try Get Encoded User String Value
368384
/// </summary>
369385
/// <param name="stringToken">The string token to read from.</param>
386+
/// <param name="jsonStringDictionary">The JSON string dictionary.</param>
370387
/// <param name="encodedUserStringValue">The encoded user string value if found.</param>
371388
/// <returns>Whether or not the Encoded User String Value was found</returns>
372389
private static bool TryGetEncodedUserStringValue(
373390
ReadOnlySpan<byte> stringToken,
391+
IJsonReadOnlyStringDictionary jsonStringDictionary,
374392
out UtfAllString encodedUserStringValue)
375393
{
376-
encodedUserStringValue = default;
377-
return false;
394+
if ((jsonStringDictionary == null)
395+
|| (!JsonBinaryEncoding.TryGetUserStringId(stringToken, out int userStringId)))
396+
{
397+
encodedUserStringValue = default;
398+
return false;
399+
}
400+
401+
return jsonStringDictionary.TryGetString(userStringId, out encodedUserStringValue);
378402
}
379403

380404
private static bool TryGetUserStringId(ReadOnlySpan<byte> stringToken, out int userStringId)
@@ -416,6 +440,7 @@ private static bool TryGetUserStringId(ReadOnlySpan<byte> stringToken, out int u
416440
private static bool TryGetBufferedLengthPrefixedString(
417441
ReadOnlyMemory<byte> buffer,
418442
ReadOnlyMemory<byte> stringToken,
443+
IJsonReadOnlyStringDictionary jsonStringDictionary,
419444
out Utf8Memory value)
420445
{
421446
ReadOnlySpan<byte> stringTokenSpan = stringToken.Span;
@@ -476,6 +501,7 @@ private static bool TryGetBufferedLengthPrefixedString(
476501
return TryGetBufferedStringValue(
477502
buffer,
478503
buffer.Slice(start: stringTokenSpan[0]),
504+
jsonStringDictionary,
479505
out value);
480506

481507
case JsonBinaryEncoding.TypeMarker.StrR2:
@@ -488,6 +514,7 @@ private static bool TryGetBufferedLengthPrefixedString(
488514
return TryGetBufferedStringValue(
489515
buffer,
490516
buffer.Slice(start: MemoryMarshal.Read<ushort>(stringTokenSpan)),
517+
jsonStringDictionary,
491518
out value);
492519

493520
case JsonBinaryEncoding.TypeMarker.StrR3:
@@ -500,6 +527,7 @@ private static bool TryGetBufferedLengthPrefixedString(
500527
return TryGetBufferedStringValue(
501528
buffer,
502529
buffer.Slice(start: MemoryMarshal.Read<UInt24>(stringTokenSpan)),
530+
jsonStringDictionary,
503531
out value);
504532

505533
case JsonBinaryEncoding.TypeMarker.StrR4:
@@ -512,6 +540,7 @@ private static bool TryGetBufferedLengthPrefixedString(
512540
return TryGetBufferedStringValue(
513541
buffer,
514542
buffer.Slice(start: (int)MemoryMarshal.Read<uint>(stringTokenSpan)),
543+
jsonStringDictionary,
515544
out value);
516545

517546
default:
@@ -534,18 +563,20 @@ private static bool TryGetBufferedLengthPrefixedString(
534563
/// Try Get Encoded String Type Marker
535564
/// </summary>
536565
/// <param name="utf8Span">the value</param>
566+
/// <param name="jsonStringDictionary">The JSON string dictionary.</param>
537567
/// <param name="multiByteTypeMarker">The encoded string type marker if found.</param>
538568
/// <returns>Whether or not the type marker was found.</returns>
539569
public static bool TryGetEncodedStringTypeMarker(
540570
Utf8Span utf8Span,
571+
IJsonReadOnlyStringDictionary jsonStringDictionary,
541572
out MultiByteTypeMarker multiByteTypeMarker)
542573
{
543574
if (JsonBinaryEncoding.TryGetEncodedSystemStringTypeMarker(utf8Span, out multiByteTypeMarker))
544575
{
545576
return true;
546577
}
547578

548-
if (JsonBinaryEncoding.TryGetEncodedUserStringTypeMarker(utf8Span, out multiByteTypeMarker))
579+
if (JsonBinaryEncoding.TryGetEncodedUserStringTypeMarker(utf8Span, jsonStringDictionary, out multiByteTypeMarker))
549580
{
550581
return true;
551582
}
@@ -581,14 +612,44 @@ private static bool TryGetEncodedSystemStringTypeMarker(
581612
/// Try Get Encoded User String Type Marker
582613
/// </summary>
583614
/// <param name="utf8Span">The value.</param>
615+
/// <param name="jsonStringDictionary">The optional json string dictionary.</param>
584616
/// <param name="multiByteTypeMarker">The multi byte type marker if found.</param>
585617
/// <returns>Whether or not the Encoded User String Type Marker was found.</returns>
586618
private static bool TryGetEncodedUserStringTypeMarker(
587619
Utf8Span utf8Span,
620+
IJsonReadOnlyStringDictionary jsonStringDictionary,
588621
out MultiByteTypeMarker multiByteTypeMarker)
589622
{
590-
multiByteTypeMarker = default;
591-
return false;
623+
if (jsonStringDictionary == null)
624+
{
625+
multiByteTypeMarker = default;
626+
return false;
627+
}
628+
629+
if (!jsonStringDictionary.TryGetStringId(utf8Span, out int stringId))
630+
{
631+
multiByteTypeMarker = default;
632+
return false;
633+
}
634+
635+
// Convert the stringId to a multibyte type marker
636+
const byte OneByteCount = TypeMarker.UserString1ByteLengthMax - TypeMarker.UserString1ByteLengthMin;
637+
if (stringId < OneByteCount)
638+
{
639+
multiByteTypeMarker = new MultiByteTypeMarker(
640+
length: 1,
641+
one: (byte)(TypeMarker.UserString1ByteLengthMin + stringId));
642+
}
643+
else
644+
{
645+
int twoByteOffset = stringId - OneByteCount;
646+
multiByteTypeMarker = new MultiByteTypeMarker(
647+
length: 2,
648+
one: (byte)((twoByteOffset / 0xFF) + TypeMarker.UserString2ByteLengthMin),
649+
two: (byte)(twoByteOffset % 0xFF));
650+
}
651+
652+
return true;
592653
}
593654

594655
[Flags]

Microsoft.Azure.Cosmos/src/Json/JsonNavigator.JsonBinaryNavigator.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ abstract partial class JsonNavigator : IJsonNavigator
2626
private sealed class JsonBinaryNavigator : JsonNavigator
2727
{
2828
private readonly ReadOnlyMemory<byte> rootBuffer;
29+
private readonly IJsonReadOnlyStringDictionary jsonStringDictionary;
2930
private readonly IJsonNavigatorNode rootNode;
3031

3132
/// <summary>
3233
/// Initializes a new instance of the JsonBinaryNavigator class
3334
/// </summary>
3435
/// <param name="buffer">The (UTF-8) buffer to navigate.</param>
35-
public JsonBinaryNavigator(ReadOnlyMemory<byte> buffer)
36+
/// <param name="jsonStringDictionary">The JSON string dictionary.</param>
37+
public JsonBinaryNavigator(
38+
ReadOnlyMemory<byte> buffer,
39+
IJsonReadOnlyStringDictionary jsonStringDictionary)
3640
{
3741
if (buffer.Length < 2)
3842
{
@@ -56,6 +60,7 @@ public JsonBinaryNavigator(ReadOnlyMemory<byte> buffer)
5660
throw new ArgumentException("Input buffer is shorter than the root node length.");
5761
}
5862

63+
this.jsonStringDictionary = jsonStringDictionary;
5964
JsonNodeType nodeType = JsonBinaryEncoding.NodeTypes.Lookup[buffer.Span[0]];
6065
this.rootNode = new BinaryNavigatorNode(nodeType, 1);
6166
}
@@ -100,6 +105,7 @@ public override bool TryGetBufferedStringValue(
100105
return JsonBinaryEncoding.TryGetBufferedStringValue(
101106
this.rootBuffer,
102107
this.rootBuffer.Slice(binaryNavigatorNode.Offset),
108+
this.jsonStringDictionary,
103109
out value);
104110
}
105111

@@ -109,7 +115,8 @@ public override UtfAnyString GetStringValue(IJsonNavigatorNode stringNode)
109115
BinaryNavigatorNode binaryNavigatorNode = this.GetNodeOfType(JsonNodeType.String, stringNode);
110116
return JsonBinaryEncoding.GetUtf8StringValue(
111117
this.rootBuffer,
112-
this.rootBuffer.Slice(binaryNavigatorNode.Offset));
118+
this.rootBuffer.Slice(binaryNavigatorNode.Offset),
119+
this.jsonStringDictionary);
113120
}
114121

115122
/// <inheritdoc />
@@ -400,7 +407,7 @@ public override IJsonReader CreateReader(IJsonNavigatorNode jsonNavigatorNode)
400407
throw new InvalidOperationException("Failed to get segment");
401408
}
402409

403-
return JsonReader.CreateBinaryFromOffset(this.rootBuffer, segment.Offset);
410+
return JsonReader.CreateBinaryFromOffset(this.rootBuffer, segment.Offset, this.jsonStringDictionary);
404411
}
405412

406413
public override void WriteNode(IJsonNavigatorNode jsonNavigatorNode, IJsonWriter jsonWriter)
@@ -423,7 +430,8 @@ public override void WriteNode(IJsonNavigatorNode jsonNavigatorNode, IJsonWriter
423430
this.rootBuffer,
424431
valueOffset: binaryNavigatorNode.Offset,
425432
externalArrayInfo: binaryNavigatorNode.ExternalArrayInfo,
426-
isFieldName);
433+
isFieldName,
434+
this.jsonStringDictionary);
427435
}
428436
else
429437
{
@@ -503,6 +511,7 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite
503511
if (JsonBinaryEncoding.TryGetBufferedStringValue(
504512
this.rootBuffer,
505513
buffer,
514+
this.jsonStringDictionary,
506515
out Utf8Memory bufferedStringValue))
507516
{
508517
if (fieldName)
@@ -516,7 +525,7 @@ private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWrite
516525
}
517526
else
518527
{
519-
string value = JsonBinaryEncoding.GetStringValue(this.rootBuffer, buffer);
528+
string value = JsonBinaryEncoding.GetStringValue(this.rootBuffer, buffer, this.jsonStringDictionary);
520529
if (fieldName)
521530
{
522531
jsonWriter.WriteFieldName(value);

0 commit comments

Comments
 (0)