Esempio n. 1
0
            public JsonBinaryReader(
                ReadOnlyMemory <byte> buffer,
                JsonStringDictionary jsonStringDictionary = null,
                bool skipValidation = false)
                : base(skipValidation)
            {
                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;
            }
            /// <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>
            /// <param name="skipValidation">whether to skip validation or not.</param>
            public JsonBinaryNavigator(
                ReadOnlyMemory <byte> buffer,
                JsonStringDictionary jsonStringDictionary,
                bool skipValidation = false)
            {
                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, NodeTypes.GetNodeType(this.buffer.Span[0]));
            }
Esempio n. 3
0
        public static JsonStringDictionary CreateFromStringArray(IReadOnlyList <string> userStrings)
        {
            if (userStrings == null)
            {
                throw new ArgumentNullException(nameof(userStrings));
            }

            JsonStringDictionary jsonStringDictionary = new JsonStringDictionary(userStrings.Count);

            for (int i = 0; i < userStrings.Count; i++)
            {
                string userString = userStrings[i];
                if (!jsonStringDictionary.TryAddString(Encoding.UTF8.GetBytes(userString).AsSpan(), out int index))
                {
                    throw new ArgumentException($"Failed to add {userString} to {nameof(JsonStringDictionary)}.");
                }

                if (index != i)
                {
                    throw new ArgumentException($"Tried to add {userString} at index {i}, but instead it was inserted at index {index}.");
                }
            }

            return(jsonStringDictionary);
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a JsonReader that can read a supplied stream (assumes UTF-8 encoding).
        /// </summary>
        /// <param name="stream">the stream to read.</param>
        /// <param name="jsonStringDictionary">The dictionary to use for binary user string encoding.</param>
        /// <param name="skipvalidation">whether or not to skip validation.</param>
        /// <returns>a concrete JsonReader that can read the supplied stream.</returns>
        public static IJsonReader Create(Stream stream, JsonStringDictionary jsonStringDictionary = null, bool skipvalidation = false)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            BinaryReader tempBinaryReader = new BinaryReader(stream, Encoding.UTF8);

            // examine the first buffer byte to determine the serialization format
            byte firstbyte = tempBinaryReader.ReadByte();

            // you have to rewind the stream since even "peeking" still reads it into the bufferedstream
            stream.Seek(0, SeekOrigin.Begin);

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

            default:
                return(new JsonTextReader(stream, Encoding.UTF8, skipvalidation));
            }
        }
Esempio n. 5
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>
        /// <param name="skipValidation">Whether or not to skip validation.</param>
        /// <returns>A concrete JsonReader that can read the supplied byte array.</returns>
        public static IJsonReader Create(ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false)
        {
            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, skipValidation));

            default:
                return(new JsonTextReader(buffer, skipValidation));
            }
        }
        /// <summary>
        /// Try Get Encoded User String Type Marker
        /// </summary>
        /// <param name="utf8Span">The value.</param>
        /// <param name="jsonStringDictionary">The optional json string dictionary.</param>
        /// <param name="multiByteTypeMarker">The multi byte type marker if found.</param>
        /// <returns>Whether or not the Encoded User String Type Marker was found.</returns>
        private static bool TryGetEncodedUserStringTypeMarker(
            Utf8Span utf8Span,
            JsonStringDictionary jsonStringDictionary,
            out MultiByteTypeMarker multiByteTypeMarker)
        {
            if (jsonStringDictionary == null)
            {
                multiByteTypeMarker = default;
                return(false);
            }

            const int MinStringLength = 2;
            const int MaxStringLength = 128;

            if ((utf8Span.Length < MinStringLength) || (utf8Span.Length > MaxStringLength))
            {
                multiByteTypeMarker = default;
                return(false);
            }

            const byte OneByteCount = TypeMarker.UserString1ByteLengthMax - TypeMarker.UserString1ByteLengthMin;

            if (!jsonStringDictionary.TryAddString(utf8Span, out int index))
            {
                multiByteTypeMarker = default;
                return(false);
            }

            // Convert the index to a multibyte type marker
            if (index < OneByteCount)
            {
                multiByteTypeMarker = new MultiByteTypeMarker(
                    length: 1,
                    one: (byte)(TypeMarker.UserString1ByteLengthMin + index));
            }
            else
            {
                int twoByteOffset = index - OneByteCount;
                multiByteTypeMarker = new MultiByteTypeMarker(
                    length: 2,
                    one: (byte)((twoByteOffset / 0xFF) + TypeMarker.UserString2ByteLengthMin),
                    two: (byte)(twoByteOffset % 0xFF));
            }

            return(true);
        }
Esempio n. 7
0
        /// <summary>
        /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text)
        /// </summary>
        /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param>
        /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
        /// <param name="skipValidation">Whether or not to skip validation</param>
        /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
        public static IJsonWriter Create(
            JsonSerializationFormat jsonSerializationFormat,
            JsonStringDictionary jsonStringDictionary = null,
            bool skipValidation = false)
        {
            switch (jsonSerializationFormat)
            {
            case JsonSerializationFormat.Text:
                return(new JsonTextWriter(Encoding.UTF8, skipValidation));

            case JsonSerializationFormat.Binary:
                return(new JsonBinaryWriter(skipValidation, jsonStringDictionary, serializeCount: false));

            default:
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat));
            }
        }
 /// <summary>
 /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text)
 /// </summary>
 /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param>
 /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
 /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param>
 /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
 public static IJsonWriter Create(
     JsonSerializationFormat jsonSerializationFormat,
     JsonStringDictionary jsonStringDictionary = null,
     int initalCapacity = 256)
 {
     return(jsonSerializationFormat switch
     {
         JsonSerializationFormat.Text => new JsonTextWriter(initalCapacity),
         JsonSerializationFormat.Binary => new JsonBinaryWriter(
             jsonStringDictionary,
             serializeCount: false),
         _ => throw new ArgumentException(
             string.Format(
                 CultureInfo.CurrentCulture,
                 RMResources.UnexpectedJsonSerializationFormat,
                 jsonSerializationFormat)),
     });
        /// <summary>
        /// Try Get Encoded String Type Marker
        /// </summary>
        /// <param name="utf8Span">the value</param>
        /// <param name="jsonStringDictionary">The JSON string dictionary.</param>
        /// <param name="multiByteTypeMarker">The encoded string type marker if found.</param>
        /// <returns>Whether or not the type marker was found.</returns>
        public static bool TryGetEncodedStringTypeMarker(
            Utf8Span utf8Span,
            JsonStringDictionary jsonStringDictionary,
            out MultiByteTypeMarker multiByteTypeMarker)
        {
            if (JsonBinaryEncoding.TryGetEncodedSystemStringTypeMarker(utf8Span, out multiByteTypeMarker))
            {
                return(true);
            }

            if (JsonBinaryEncoding.TryGetEncodedUserStringTypeMarker(utf8Span, jsonStringDictionary, out multiByteTypeMarker))
            {
                return(true);
            }

            multiByteTypeMarker = default;
            return(false);
        }
            /// <summary>
            /// Initializes a new instance of the JsonBinaryWriter class.
            /// </summary>
            /// <param name="jsonStringDictionary">The JSON string dictionary used for user string encoding.</param>
            /// <param name="serializeCount">Whether to serialize the count for object and array typemarkers.</param>
            public JsonBinaryWriter(
                JsonStringDictionary jsonStringDictionary = null,
                bool serializeCount = false)
            {
                this.binaryWriter     = new JsonBinaryMemoryWriter();
                this.bufferedContexts = new Stack <BeginOffsetAndCount>();
                this.serializeCount   = serializeCount;
                this.reservationSize  = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength + (this.serializeCount ? JsonBinaryEncoding.OneByteCount : 0);

                // Write the serialization format as the very first byte
                byte binaryTypeMarker = (byte)JsonSerializationFormat.Binary;

                this.binaryWriter.Write(binaryTypeMarker);

                // Push on the outermost context
                this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength));
                this.jsonStringDictionary = jsonStringDictionary;
            }
            /// <summary>
            /// Initializes a new instance of the JsonBinaryWriter class.
            /// </summary>
            /// <param name="skipValidation">Whether to skip validation on the JsonObjectState.</param>
            /// <param name="jsonStringDictionary">The JSON string dictionary used for user string encoding.</param>
            /// <param name="serializeCount">Whether to serialize the count for object and array typemarkers.</param>
            public JsonBinaryWriter(
                bool skipValidation,
                JsonStringDictionary jsonStringDictionary = null,
                bool serializeCount = false)
                : base(skipValidation)
            {
                this.binaryWriter     = new BinaryWriter(new MemoryStream());
                this.bufferedContexts = new Stack <BeginOffsetAndCount>();
                this.serializeCount   = serializeCount;
                this.reservationSize  = TypeMarker + TwoByteLength + (this.serializeCount ? TwoByteCount : 0);

                // Write the serialization format as the very first byte
                this.binaryWriter.Write((byte)JsonSerializationFormat.Binary);

                // Push on the outermost context
                this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength));
                this.jsonStringDictionary = jsonStringDictionary;
            }
        /// <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, JsonStringDictionary 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));
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text)
        /// </summary>
        /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param>
        /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
        /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param>
        /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
        public static IJsonWriter Create(
            JsonSerializationFormat jsonSerializationFormat,
            JsonStringDictionary jsonStringDictionary = null,
            int initalCapacity = 256)
        {
            switch (jsonSerializationFormat)
            {
            case JsonSerializationFormat.Text:
                return(new JsonTextWriter(initalCapacity));

            case JsonSerializationFormat.Binary:
                return(new JsonBinaryWriter(
                           jsonStringDictionary,
                           serializeCount: false));

            default:
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat));
            }
        }
Esempio n. 14
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>
        /// <param name="skipValidation">Whether or not to skip validation.</param>
        /// <returns>A concrete JsonReader that can read the supplied byte array.</returns>
        public static IJsonReader Create(byte[] buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            byte firstByte = buffer[0];

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

            default:
                return(new JsonTextReader(buffer, skipValidation));
            }
        }
Esempio n. 15
0
        /// <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>
        /// <param name="skipValidation">Whether validation should be skipped.</param>
        /// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns>
        public static IJsonNavigator Create(
            ReadOnlyMemory <byte> buffer,
            JsonStringDictionary jsonStringDictionary = null,
            bool skipValidation = false)
        {
            // Examine the first buffer byte to determine the serialization format
            byte firstByte = buffer.Span[0];

            switch ((JsonSerializationFormat)firstByte)
            {
            // Explicitly pick from the set of supported formats
            case JsonSerializationFormat.Binary:
                return(new JsonBinaryNavigator(buffer, jsonStringDictionary, skipValidation));

            default:
                // or otherwise assume text format
                return(new JsonTextNavigator(buffer, skipValidation));
            }
        }
            /// <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>
            /// <param name="skipValidation">whether to skip validation or not.</param>
            public JsonBinaryNavigator(byte[] buffer, JsonStringDictionary jsonStringDictionary, bool skipValidation = false)
            {
                if (buffer == null)
                {
                    throw new ArgumentNullException($"{nameof(buffer)} can not be null");
                }

                if (buffer.Length < 1)
                {
                    throw new ArgumentException($"{nameof(buffer)} must have at least one byte.");
                }

                this.rootNode = new BinaryNode(1, JsonBinaryEncoding.GetNodeType(buffer[1]));

                // false, since stream is not writeable
                // true, since buffer is visible
                this.binaryReader         = new LittleEndianBinaryReader(new MemoryStream(buffer, 0, buffer.Length, false, true));
                this.buffer               = buffer;
                this.jsonStringDictionary = jsonStringDictionary;
            }
Esempio n. 17
0
        /// <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>
        /// <param name="skipValidation">Whether validation should be skipped.</param>
        /// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns>
        public static IJsonNavigator Create(byte[] buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

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

            switch ((JsonSerializationFormat)firstByte)
            {
            // Explicitly pick from the set of supported formats
            case JsonSerializationFormat.Binary:
                return(new JsonBinaryNavigator(buffer, jsonStringDictionary, skipValidation));

            default:
                // or otherwise assume text format
                return(new JsonTextNavigator(buffer, skipValidation));
            }
        }
Esempio n. 18
0
 /// <summary>
 /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text)
 /// </summary>
 /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param>
 /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param>
 /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param>
 /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns>
 public static IJsonWriter Create(
     JsonSerializationFormat jsonSerializationFormat,
     JsonStringDictionary jsonStringDictionary = null,
     int initalCapacity = 256) => jsonSerializationFormat switch
 {