@@ -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 ]
0 commit comments