/// <summary>
        /// Gets the string value from the binary reader.
        /// </summary>
        /// <param name="stringToken">The buffer that has the string.</param>
        /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
        /// <returns>A string value from the binary reader.</returns>
        public static string GetStringValue(
            Utf8Memory stringToken,
            IReadOnlyJsonStringDictionary jsonStringDictionary)
        {
            if (stringToken.IsEmpty)
            {
                throw new JsonInvalidTokenException();
            }

            if (JsonBinaryEncoding.TryGetBufferedLengthPrefixedString(
                    stringToken,
                    out Utf8Memory lengthPrefixedString))
            {
                return(lengthPrefixedString.ToString());
            }

            if (JsonBinaryEncoding.TryGetEncodedStringValue(
                    stringToken.Span,
                    jsonStringDictionary,
                    out UtfAllString encodedStringValue))
            {
                return(encodedStringValue.Utf16String);
            }

            throw new JsonInvalidTokenException();
        }
Example #2
0
            public JsonBinaryReader(
                ReadOnlyMemory <byte> buffer,
                IReadOnlyJsonStringDictionary jsonStringDictionary = null)
            {
                if (buffer.Length < 2)
                {
                    throw new ArgumentException($"{nameof(buffer)} must have at least two byte.");
                }

                if (buffer.Span[0] != (byte)JsonSerializationFormat.Binary)
                {
                    throw new ArgumentNullException("buffer must be binary encoded.");
                }

                // 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
                int jsonValueLength = JsonBinaryEncoding.GetValueLength(buffer.Span);

                if (buffer.Length < jsonValueLength)
                {
                    throw new ArgumentException("buffer is shorter than the length prefix.");
                }

                buffer = buffer.Slice(0, jsonValueLength);

                this.jsonBinaryBuffer       = new JsonBinaryMemoryReader(buffer);
                this.arrayAndObjectEndStack = new Stack <int>();
                this.jsonStringDictionary   = jsonStringDictionary;
            }
Example #3
0
            /// <summary>
            /// Initializes a new instance of the JsonBinaryNavigator class
            /// </summary>
            /// <param name="buffer">The (UTF-8) buffer to navigate.</param>
            /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
            public JsonBinaryNavigator(
                ReadOnlyMemory <byte> buffer,
                IReadOnlyJsonStringDictionary jsonStringDictionary)
            {
                if (buffer.Length < 2)
                {
                    throw new ArgumentException($"{nameof(buffer)} must have at least two byte.");
                }

                if (buffer.Span[0] != (byte)JsonSerializationFormat.Binary)
                {
                    throw new ArgumentNullException("buffer must be binary encoded.");
                }

                // 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
                int jsonValueLength = JsonBinaryEncoding.GetValueLength(buffer.Span);

                if (buffer.Length < jsonValueLength)
                {
                    throw new ArgumentException("buffer is shorter than the length prefix.");
                }

                buffer = buffer.Slice(0, jsonValueLength);

                this.buffer = buffer;
                this.jsonStringDictionary = jsonStringDictionary;
                this.rootNode             = new BinaryNavigatorNode(this.buffer, JsonBinaryEncoding.NodeTypes.GetNodeType(this.buffer.Span[0]));
            }
        public static bool TryGetBufferedStringValue(
            Utf8Memory stringToken,
            IReadOnlyJsonStringDictionary jsonStringDictionary,
            out Utf8Memory value)
        {
            if (stringToken.IsEmpty)
            {
                value = default;
                return(false);
            }

            if (JsonBinaryEncoding.TryGetBufferedLengthPrefixedString(
                    stringToken,
                    out value))
            {
                return(true);
            }

            if (JsonBinaryEncoding.TryGetEncodedStringValue(
                    stringToken.Span,
                    jsonStringDictionary,
                    out UtfAllString encodedStringValue))
            {
                value = encodedStringValue.Utf8EscapedString;
                return(true);
            }

            value = default;
            return(false);
        }
        public bool Equals(IReadOnlyJsonStringDictionary other)
        {
            if (other == null)
            {
                return(false);
            }

            if (!(other is JsonStringDictionary otherDictionary))
            {
                throw new NotImplementedException();
            }

            return(this.Equals(otherDictionary));
        }
Example #6
0
            private bool IsSameStringDictionary(IReadOnlyJsonStringDictionary jsonStringDictionary)
            {
                if (object.ReferenceEquals(this.jsonStringDictionary, jsonStringDictionary))
                {
                    return(true);
                }

                if ((this.jsonStringDictionary != null) && (jsonStringDictionary != null))
                {
                    return(this.jsonStringDictionary.Equals(jsonStringDictionary));
                }

                return(false);
            }
        /// <summary>
        /// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding) with format marker.
        /// </summary>
        /// <param name="buffer">The byte array (with format marker) to read from.</param>
        /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
        /// <returns>A concrete JsonReader that can read the supplied byte array.</returns>
        public static IJsonReader Create(ReadOnlyMemory <byte> buffer, IReadOnlyJsonStringDictionary jsonStringDictionary = null)
        {
            if (buffer.IsEmpty)
            {
                throw new ArgumentOutOfRangeException($"{nameof(buffer)} can not be empty.");
            }

            byte firstByte = buffer.Span[0];

            // Explicitly pick from the set of supported formats, or otherwise assume text format
            JsonSerializationFormat jsonSerializationFormat = (firstByte == (byte)JsonSerializationFormat.Binary) ? JsonSerializationFormat.Binary : JsonSerializationFormat.Text;

            return(JsonReader.Create(jsonSerializationFormat, buffer, jsonStringDictionary));
        }
        /// <summary>
        /// Gets the string value from the binary reader.
        /// </summary>
        /// <param name="stringToken">The buffer that has the string.</param>
        /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
        /// <returns>A string value from the binary reader.</returns>
        public static string GetStringValue(
            Utf8Memory stringToken,
            IReadOnlyJsonStringDictionary jsonStringDictionary)
        {
            if (stringToken.IsEmpty)
            {
                throw new JsonInvalidTokenException();
            }

            if (!JsonBinaryEncoding.TryGetBufferedStringValue(stringToken, jsonStringDictionary, out Utf8Memory bufferedUtf8StringValue))
            {
                throw new JsonInvalidTokenException();
            }

            return(bufferedUtf8StringValue.ToString());
        }
        /// <summary>
        /// Creates a JsonReader with a given serialization format and byte array.
        /// </summary>
        /// <param name="jsonSerializationFormat">The serialization format of the payload.</param>
        /// <param name="buffer">The buffer to read from.</param>
        /// <param name="jsonStringDictionary">The optional dictionary to decode strings.</param>
        /// <returns>An <see cref="IJsonReader"/> for the buffer, format, and dictionary.</returns>
        public static IJsonReader Create(
            JsonSerializationFormat jsonSerializationFormat,
            ReadOnlyMemory <byte> buffer,
            IReadOnlyJsonStringDictionary jsonStringDictionary = null)
        {
            if (buffer.IsEmpty)
            {
                throw new ArgumentOutOfRangeException($"{nameof(buffer)} can not be empty.");
            }

            // Explicitly pick from the set of supported formats, or otherwise assume text format
            return(jsonSerializationFormat switch
            {
                JsonSerializationFormat.Binary => new JsonBinaryReader(buffer, jsonStringDictionary),
                JsonSerializationFormat.Text => new JsonTextReader(buffer),
                _ => throw new ArgumentOutOfRangeException($"Unknown {nameof(JsonSerializationFormat)}: {jsonSerializationFormat}."),
            });
        /// <summary>
        /// Try Get Encoded String Value
        /// </summary>
        /// <param name="stringToken">The string token to read from.</param>
        /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
        /// <param name="value">The encoded string if found.</param>
        /// <returns>Encoded String Value</returns>
        private static bool TryGetEncodedStringValue(
            Utf8Span stringToken,
            IReadOnlyJsonStringDictionary jsonStringDictionary,
            out UtfAllString value)
        {
            if (JsonBinaryEncoding.TryGetEncodedSystemStringValue(stringToken, out value))
            {
                return(true);
            }

            if (JsonBinaryEncoding.TryGetEncodedUserStringValue(stringToken, jsonStringDictionary, out value))
            {
                return(true);
            }

            value = default;
            return(false);
        }
Example #11
0
        /// <summary>
        /// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding).
        /// </summary>
        /// <param name="buffer">The byte array to read from.</param>
        /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
        /// <returns>A concrete JsonReader that can read the supplied byte array.</returns>
        public static IJsonReader Create(ReadOnlyMemory <byte> buffer, IReadOnlyJsonStringDictionary jsonStringDictionary = null)
        {
            if (buffer.IsEmpty)
            {
                throw new ArgumentOutOfRangeException($"{nameof(buffer)} can not be empty.");
            }

            byte firstByte = buffer.Span[0];

            // Explicitly pick from the set of supported formats, or otherwise assume text format
            switch ((JsonSerializationFormat)firstByte)
            {
            case JsonSerializationFormat.Binary:
                return(new JsonBinaryReader(buffer, jsonStringDictionary));

            default:
                return(new JsonTextReader(buffer));
            }
        }
        /// <summary>
        /// Try Get Encoded User String Value
        /// </summary>
        /// <param name="stringToken">The string token to read from.</param>
        /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
        /// <param name="encodedUserStringValue">The encoded user string value if found.</param>
        /// <returns>Whether or not the Encoded User String Value was found</returns>
        private static bool TryGetEncodedUserStringValue(
            Utf8Span stringToken,
            IReadOnlyJsonStringDictionary jsonStringDictionary,
            out UtfAllString encodedUserStringValue)
        {
            if (jsonStringDictionary == null)
            {
                encodedUserStringValue = default;
                return(false);
            }

            if (!JsonBinaryEncoding.TryGetUserStringId(stringToken, out int userStringId))
            {
                encodedUserStringValue = default;
                return(false);
            }

            return(jsonStringDictionary.TryGetStringAtIndex(userStringId, out encodedUserStringValue));
        }
        /// <summary>
        /// Creates a JsonNavigator that can navigate a supplied buffer
        /// </summary>
        /// <param name="buffer">The buffer to navigate</param>
        /// <param name="jsonStringDictionary">The optional json string dictionary for binary encoding.</param>
        /// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns>
        public static IJsonNavigator Create(
            ReadOnlyMemory <byte> buffer,
            IReadOnlyJsonStringDictionary jsonStringDictionary = null)
        {
            if (buffer.IsEmpty)
            {
                throw new ArgumentOutOfRangeException($"{nameof(buffer)} can not be empty.");
            }

            // Examine the first buffer byte to determine the serialization format
            byte firstByte = buffer.Span[0];

            return(((JsonSerializationFormat)firstByte) switch
            {
                // Explicitly pick from the set of supported formats
                JsonSerializationFormat.Binary => new JsonBinaryNavigator(buffer, jsonStringDictionary),

                // or otherwise assume text format
                _ => new JsonTextNavigator(buffer),
            });
            public JsonBinaryReader(
                ReadOnlyMemory<byte> buffer,
                IReadOnlyJsonStringDictionary jsonStringDictionary = null)
            {
                if (buffer.IsEmpty)
                {
                    throw new ArgumentException($"{nameof(buffer)} must not be empty.");
                }

                // 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.");
                }

                buffer = buffer.Slice(0, jsonValueLength);

                this.jsonBinaryBuffer = new JsonBinaryMemoryReader(buffer);
                this.arrayAndObjectEndStack = new Stack<int>();
                this.jsonStringDictionary = jsonStringDictionary;
            }
            internal JsonBinaryReader(
                ReadOnlyMemory <byte> rootBuffer,
                int?indexToStartFrom = null,
                IReadOnlyJsonStringDictionary jsonStringDictionary = null)
            {
                if (rootBuffer.IsEmpty)
                {
                    throw new ArgumentException($"{nameof(rootBuffer)} must not be empty.");
                }

                this.rootBuffer = rootBuffer;

                ReadOnlyMemory <byte> readerBuffer = this.rootBuffer;

                if (indexToStartFrom.HasValue)
                {
                    readerBuffer = readerBuffer.Slice(start: indexToStartFrom.Value);
                }
                else
                {
                    // Skip the 0x80
                    readerBuffer = readerBuffer.Slice(start: 1);
                }

                // Only navigate the outer most json value and trim off trailing bytes
                int jsonValueLength = JsonBinaryEncoding.GetValueLength(readerBuffer.Span);

                if (readerBuffer.Length < jsonValueLength)
                {
                    throw new ArgumentException("buffer is shorter than the length prefix.");
                }

                readerBuffer = readerBuffer.Slice(0, jsonValueLength);

                // offset for the 0x80 binary type marker
                this.jsonBinaryBuffer       = new JsonBinaryMemoryReader(readerBuffer);
                this.arrayAndObjectEndStack = new Stack <int>();
                this.jsonStringDictionary   = jsonStringDictionary;
            }
Example #16
0
 public void WriteRawJsonValue(
     ReadOnlyMemory <byte> rawJsonValue,
     bool isFieldName,
     bool isRootNode,
     IReadOnlyJsonStringDictionary jsonStringDictionary)
 {
     // Only if the we attempt to write the root node as is the input and output have the same dictionary encoding
     if (this.IsSameStringDictionary(jsonStringDictionary) && 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(rawJsonValue, isFieldName, jsonStringDictionary);
     }
 }
Example #17
0
            private void ForceRewriteRawJsonValue(
                ReadOnlyMemory <byte> rawJsonValue,
                bool isFieldName,
                IReadOnlyJsonStringDictionary jsonStringDictionary)
            {
                byte typeMarker = rawJsonValue.Span[0];

                if (!JsonBinaryEncoding.TypeMarker.IsSystemString(typeMarker) &&
                    !JsonBinaryEncoding.TypeMarker.IsEmptyArray(typeMarker) &&
                    !JsonBinaryEncoding.TypeMarker.IsEmptyObject(typeMarker))
                {
                    JsonNodeType nodeType = JsonBinaryEncoding.NodeTypes.GetNodeType(typeMarker);
                    switch (nodeType)
                    {
                    case JsonNodeType.String:
                    {
                        if (!JsonBinaryEncoding.TryGetBufferedStringValue(
                                Utf8Memory.UnsafeCreateNoValidation(rawJsonValue),
                                jsonStringDictionary,
                                out Utf8Memory bufferedStringValue))
                        {
                            throw new InvalidOperationException("Excepted to get the buffered string value.");
                        }

                        if (isFieldName)
                        {
                            this.WriteFieldName(bufferedStringValue.Span);
                        }
                        else
                        {
                            this.WriteStringValue(bufferedStringValue.Span);
                        }

                        return;
                    }

                    case JsonNodeType.Array:
                    {
                        this.WriteArrayStart();

                        foreach (ReadOnlyMemory <byte> arrayItem in JsonBinaryEncoding.Enumerator.GetArrayItems(rawJsonValue))
                        {
                            this.ForceRewriteRawJsonValue(arrayItem, isFieldName, jsonStringDictionary);
                        }

                        this.WriteArrayEnd();

                        return;
                    }

                    case JsonNodeType.Object:
                    {
                        this.WriteObjectStart();

                        foreach (JsonBinaryEncoding.Enumerator.ObjectProperty property in JsonBinaryEncoding.Enumerator.GetObjectProperties(rawJsonValue))
                        {
                            this.ForceRewriteRawJsonValue(property.Name, isFieldName: true, jsonStringDictionary);
                            this.ForceRewriteRawJsonValue(property.Value, isFieldName: false, jsonStringDictionary);
                        }

                        this.WriteObjectEnd();

                        return;
                    }
                    }
                }

                // 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++;
                }
            }
 public JsonBinaryReader(
     ReadOnlyMemory <byte> buffer,
     IReadOnlyJsonStringDictionary jsonStringDictionary = null)
     : this(buffer, indexToStartFrom : null, jsonStringDictionary : jsonStringDictionary)
 {
 }