예제 #1
0
        private void BuildPositions()
        {
            using (Stream stream = _streamProvider())
                using (JsonPositionedTextReader reader = new JsonPositionedTextReader(() => stream))
                {
                    stream.Seek(_start, SeekOrigin.Begin);
                    reader.Read();

                    BuildPositions(reader, _start);
                }
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JsonPositionedTextReader r = reader as JsonPositionedTextReader;

            if (r == null)
            {
                throw new InvalidOperationException($"{nameof(DeferredListConverter<T>)} requires a {nameof(JsonPositionedTextReader)} be used for deserialization.");
            }

            return(new DeferredList <T>(serializer, r));
        }
예제 #3
0
        public DeferredList(JsonSerializer jsonSerializer, JsonPositionedTextReader reader, bool buildPositionsNow = true)
        {
            _jsonSerializer = jsonSerializer;
            _streamProvider = reader.StreamProvider;
            _start          = reader.TokenPosition;
            _count          = -1;

            if (buildPositionsNow)
            {
                BuildPositions(reader, 0);
            }
            else
            {
                // We have to skip the array; it is free to get the count now so we don't have to walk again to get it.
                CountOnly(reader);
            }
        }
예제 #4
0
        public DeferredDictionary(JsonSerializer jsonSerializer, JsonPositionedTextReader reader, bool buildPositionsNow = false)
        {
            _jsonSerializer = jsonSerializer;
            _streamProvider = reader.StreamProvider;
            _start          = reader.TokenPosition;

            // We have the JsonTextReader, which must scan to after the collection to resume building the outer object
            // We may as well make the map of element positions.
            if (buildPositionsNow)
            {
                BuildPositions(reader, 0);
            }
            else
            {
                reader.Skip();
            }
        }
예제 #5
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader is JsonInnerTextReader)
            {
                // Nested in another deferred container, read the list non-deferred
                return(serializer.Deserialize <List <T> >(reader));
            }

            // If we don't have a positioned reader, we must return an error
            JsonPositionedTextReader r = reader as JsonPositionedTextReader;

            if (r == null)
            {
                throw new InvalidOperationException($"{nameof(DeferredListConverter<T>)} requires a {nameof(JsonPositionedTextReader)} be used for deserialization.");
            }

            return(new DeferredList <T>(serializer, r));
        }
예제 #6
0
        private void BuildPositions(JsonPositionedTextReader reader, long currentOffset)
        {
            List <long> positions = new List <long>();

            while (true)
            {
                reader.Read();
                if (reader.TokenType == JsonToken.EndArray)
                {
                    break;
                }

                positions.Add(currentOffset + reader.TokenPosition);
                reader.Skip();
            }

            _itemPositions = positions.ToArray();
            _count         = positions.Count;
        }
예제 #7
0
        private void CountOnly(JsonPositionedTextReader reader)
        {
            int count = 0;

            // StartArray
            reader.Read();

            while (true)
            {
                reader.Read();
                if (reader.TokenType == JsonToken.EndArray)
                {
                    break;
                }

                count++;
                reader.Skip();
            }

            _count = count;
        }
예제 #8
0
        private void BuildPositions(JsonPositionedTextReader reader, long currentOffset)
        {
            var result = new Dictionary <int, long>();

            while (true)
            {
                // Find the position just before the PropertyName (we need to read it back later to confirm the string matches)
                long keyPosition = currentOffset + reader.TokenPosition + 1;

                reader.Read();
                if (reader.TokenType == JsonToken.EndObject)
                {
                    break;
                }

                if (reader.TokenType != JsonToken.PropertyName)
                {
                    throw new InvalidDataException($"@({reader.LineNumber}, {reader.LinePosition}): Expected property name, found {reader.TokenType} \"{reader.Value}\".");
                }

                // Read JSON object name (Dictionary key)
                string key     = (string)reader.Value;
                int    keyHash = key.GetHashCode();

                // Skip the value
                reader.Read();
                reader.Skip();

                // Add the hash to the position to our Dictionary; resolve collisions by incrementing
                while (result.ContainsKey(keyHash))
                {
                    keyHash++;
                }
                result[keyHash] = keyPosition;
            }

            _itemPositions = result;
        }
예제 #9
0
        private static void CompareReadNormalToReadDeferred(string filePath)
        {
            LogModelSampleBuilder.EnsureSamplesBuilt();
            JsonSerializer serializer = new JsonSerializer();

            Log expected;
            Log actual;

            // Read normally (JsonSerializer -> JsonTextReader -> StreamReader)
            using (JsonTextReader reader = new JsonTextReader(new StreamReader(filePath)))
            {
                expected = serializer.Deserialize <Log>(reader);
                Assert.IsType <Dictionary <string, CodeContext> >(expected.CodeContexts);
                Assert.IsType <List <LogMessage> >(expected.Messages);
            }

            // Read with Deferred collections
            serializer.ContractResolver = new LogModelDeferredContractResolver();
            using (JsonPositionedTextReader reader = new JsonPositionedTextReader(filePath))
            {
                actual = serializer.Deserialize <Log>(reader);
                Assert.IsType <DeferredDictionary <CodeContext> >(actual.CodeContexts);
                Assert.IsType <DeferredList <LogMessage> >(actual.Messages);
            }

            // Deep compare objects which were returned
            AssertEqual(expected, actual);

            // DeferredList Code Coverage - CopyTo()
            LogMessage[] messages = new LogMessage[actual.Messages.Count + 1];
            actual.Messages.CopyTo(messages, 1);
            if (actual.Messages.Count > 0)
            {
                Assert.Equal <LogMessage>(actual.Messages[0], messages[1]);
            }

            // DeferredDictionary Code Coverage
            CodeContext context;

            // TryGetValue
            Assert.False(actual.CodeContexts.TryGetValue("missing", out context));
            if (actual.CodeContexts.Count > 0)
            {
                Assert.True(actual.CodeContexts.TryGetValue("load", out context));
            }

            // ContainsKey
            Assert.False(actual.CodeContexts.ContainsKey("missing"));
            if (actual.CodeContexts.Count > 0)
            {
                Assert.True(actual.CodeContexts.ContainsKey("load"));
            }

            // Contains
            context = new CodeContext()
            {
                Name = "LoadRules()", Type = CodeContextType.Method, ParentContextID = "run"
            };
            Assert.False(actual.CodeContexts.Contains(new KeyValuePair <string, CodeContext>("missing", context)));        // Missing Key
            Assert.False(actual.CodeContexts.Contains(new KeyValuePair <string, CodeContext>("run", context)));            // Different Value

            if (actual.CodeContexts.Count > 0)
            {
                Assert.True(actual.CodeContexts.Contains(new KeyValuePair <string, CodeContext>("load", context)));        // Match
                Assert.False(actual.CodeContexts.Contains(new KeyValuePair <string, CodeContext>("load", null)));          // Match vs. Null
            }

            // CopyTo
            KeyValuePair <string, CodeContext>[] contexts = new KeyValuePair <string, CodeContext> [actual.CodeContexts.Count + 1];
            actual.CodeContexts.CopyTo(contexts, 1);
            if (actual.CodeContexts.Count > 0)
            {
                Assert.Equal(actual.CodeContexts.First(), contexts[1]);
            }

            // Enumeration
            Dictionary <string, CodeContext> contextsCopy = new Dictionary <string, CodeContext>();

            foreach (KeyValuePair <string, CodeContext> pair in actual.CodeContexts)
            {
                contextsCopy[pair.Key] = pair.Value;
            }
            Assert.Equal(actual.CodeContexts.Count, contextsCopy.Count);

            // Enumerate Keys
            int keyCount = 0;

            foreach (string key in actual.CodeContexts.Keys)
            {
                Assert.True(contextsCopy.ContainsKey(key));
                keyCount++;
            }
            Assert.Equal(contextsCopy.Count, keyCount);

            // Enumerate Values
            int valueCount = 0;

            foreach (CodeContext value in actual.CodeContexts.Values)
            {
                Assert.True(contextsCopy.ContainsValue(value));
                valueCount++;
            }
            Assert.Equal(contextsCopy.Count, valueCount);
        }