private void Assert(BsonTrie<int> trie, string name) { var subject = new TrieNameDecoder<int>(trie); using (var memoryStream = new MemoryStream()) using (var bsonStream = new BsonStreamAdapter(memoryStream)) { bsonStream.WriteCString(name); bsonStream.WriteInt32(20); bsonStream.Position = 0; var result = subject.Decode(bsonStream, Utf8Encodings.Strict); result.Should().Be(name); } }
private void Assert(BsonTrie <int> trie, string name) { var subject = new TrieNameDecoder <int>(trie); using (var memoryStream = new MemoryStream()) using (var bsonStream = new BsonStreamAdapter(memoryStream)) { bsonStream.WriteCString(name); bsonStream.WriteInt32(20); bsonStream.Position = 0; var result = subject.Decode(bsonStream, Utf8Encodings.Strict); result.Should().Be(name); } }
// private methods private void Assert(string name, TrieNameDecoder <int> subject, bool found, int value) { using (var memoryStream = new MemoryStream()) using (var bsonStream = new BsonStreamAdapter(memoryStream)) { bsonStream.WriteCString(name); bsonStream.WriteInt32(20); bsonStream.Position = 0; var result = subject.Decode(bsonStream, Utf8Encodings.Strict); result.Should().Be(name); subject.Found.Should().Be(found); subject.Value.Should().Be(value); } }
private void Assert(BsonTrie <int> trie, string name, bool found, int value) { // test multiple calls to the same TrieDecoder instance var subject = new TrieNameDecoder <int>(trie); // 1st pass: assert calling test's expectation Assert(name, subject, found, value); // 2rd pass: assert calling test's expectation once again Assert(name, subject, found, value); // 3rd pass: different value in stream --> assert "found: false" and "value: default" Assert("doesn't exist in trie", subject, false, default); // 4th pass: assert calling test's expectation once again Assert(name, subject, found, value); }
// public methods /// <summary> /// Deserializes the members. /// </summary> /// <param name="context">The deserialization context.</param> /// <param name="memberHandler">The member handler.</param> /// <returns>The found member flags.</returns> public long DeserializeMembers(BsonDeserializationContext context, Action <string, long> memberHandler) { var reader = context.Reader; var foundMemberFlags = 0L; reader.ReadStartDocument(); var trieDecoder = new TrieNameDecoder <long>(_trie); while (reader.ReadBsonType() != 0) { var elementName = reader.ReadName(trieDecoder); long memberFlag; if (trieDecoder.Found) { memberFlag = trieDecoder.Value; } else { if (_extraMemberFlag == 0) { throw new BsonSerializationException(string.Format( "Invalid element: '{0}'.", elementName)); } else { memberFlag = _extraMemberFlag; } } memberHandler(elementName, memberFlag); foundMemberFlags |= memberFlag; } reader.ReadEndDocument(); var missingRequiredMemberFlags = _requiredMemberFlags & ~foundMemberFlags; if (missingRequiredMemberFlags != 0) { var missingRequiredMember = FindFirstMissingRequiredMember(missingRequiredMemberFlags); throw new BsonSerializationException(string.Format( "Missing element: '{0}'.", missingRequiredMember.ElementName)); } return(foundMemberFlags); }
/// <summary> /// Deserializes a value. /// </summary> /// <param name="context">The deserialization context.</param> /// <returns>A deserialized value.</returns> public TClass DeserializeClass(BsonDeserializationContext context) { var bsonReader = context.Reader; var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType != BsonType.Document) { var message = string.Format( "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.", typeof(TClass).FullName, bsonType); throw new FormatException(message); } Dictionary <string, object> values = null; var document = default(TClass); #if NET452 || NETSTANDARD2_0 ISupportInitialize supportsInitialization = null; #endif if (_classMap.HasCreatorMaps) { // for creator-based deserialization we first gather the values in a dictionary and then call a matching creator values = new Dictionary <string, object>(); } else { // for mutable classes we deserialize the values directly into the result object document = (TClass)_classMap.CreateInstance(); #if NET452 || NETSTANDARD2_0 supportsInitialization = document as ISupportInitialize; if (supportsInitialization != null) { supportsInitialization.BeginInit(); } #endif #if NETSTANDARD1_5 if (_beginInitMethodInfo != null) { _beginInitMethodInfo.Invoke(document, new object[0]); } #endif } var discriminatorConvention = _classMap.GetDiscriminatorConvention(); var allMemberMaps = _classMap.AllMemberMaps; var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex; var memberMapBitArray = FastMemberMapHelper.GetBitArray(allMemberMaps.Count); bsonReader.ReadStartDocument(); var elementTrie = _classMap.ElementTrie; while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var trieDecoder = new TrieNameDecoder <int>(elementTrie); var elementName = bsonReader.ReadName(trieDecoder); if (trieDecoder.Found) { var memberMapIndex = trieDecoder.Value; var memberMap = allMemberMaps[memberMapIndex]; if (memberMapIndex != extraElementsMemberMapIndex) { if (document != null) { if (memberMap.IsReadOnly) { bsonReader.SkipValue(); } else { var value = DeserializeMemberValue(context, memberMap); memberMap.Setter(document, value); } } else { var value = DeserializeMemberValue(context, memberMap); values[elementName] = value; } } else { if (document != null) { DeserializeExtraElementMember(context, document, elementName, memberMap); } else { DeserializeExtraElementValue(context, values, elementName, memberMap); } } memberMapBitArray[memberMapIndex >> 5] |= 1U << (memberMapIndex & 31); } else { if (elementName == discriminatorConvention.ElementName) { bsonReader.SkipValue(); // skip over discriminator continue; } if (extraElementsMemberMapIndex >= 0) { var extraElementsMemberMap = _classMap.ExtraElementsMemberMap; if (document != null) { DeserializeExtraElementMember(context, document, elementName, extraElementsMemberMap); } else { DeserializeExtraElementValue(context, values, elementName, extraElementsMemberMap); } memberMapBitArray[extraElementsMemberMapIndex >> 5] |= 1U << (extraElementsMemberMapIndex & 31); } else if (_classMap.IgnoreExtraElements) { bsonReader.SkipValue(); } else { var message = string.Format( "Element '{0}' does not match any field or property of class {1}.", elementName, _classMap.ClassType.FullName); throw new FormatException(message); } } } bsonReader.ReadEndDocument(); // check any members left over that we didn't have elements for (in blocks of 32 elements at a time) for (var bitArrayIndex = 0; bitArrayIndex < memberMapBitArray.Length; ++bitArrayIndex) { var memberMapIndex = bitArrayIndex << 5; var memberMapBlock = ~memberMapBitArray[bitArrayIndex]; // notice that bits are flipped so 1's are now the missing elements // work through this memberMapBlock of 32 elements while (true) { // examine missing elements (memberMapBlock is shifted right as we work through the block) for (; (memberMapBlock & 1) != 0; ++memberMapIndex, memberMapBlock >>= 1) { var memberMap = allMemberMaps[memberMapIndex]; if (memberMap.IsReadOnly) { continue; } if (memberMap.IsRequired) { var fieldOrProperty = (memberMap.MemberInfo is FieldInfo) ? "field" : "property"; var message = string.Format( "Required element '{0}' for {1} '{2}' of class {3} is missing.", memberMap.ElementName, fieldOrProperty, memberMap.MemberName, _classMap.ClassType.FullName); throw new FormatException(message); } if (document != null) { memberMap.ApplyDefaultValue(document); } else if (memberMap.IsDefaultValueSpecified && !memberMap.IsReadOnly) { values[memberMap.ElementName] = memberMap.DefaultValue; } } if (memberMapBlock == 0) { break; } // skip ahead to the next missing element var leastSignificantBit = FastMemberMapHelper.GetLeastSignificantBit(memberMapBlock); memberMapIndex += leastSignificantBit; memberMapBlock >>= leastSignificantBit; } } if (document != null) { #if NET452 || NETSTANDARD2_0 if (supportsInitialization != null) { supportsInitialization.EndInit(); } #endif #if NETSTANDARD1_5 if (_endInitMethodInfo != null) { _endInitMethodInfo.Invoke(document, new object[0]); } #endif return(document); } else { return(CreateInstanceUsingCreator(values)); } }
// public methods /// <summary> /// Deserializes the members. /// </summary> /// <param name="context">The deserialization context.</param> /// <param name="memberHandler">The member handler.</param> /// <returns>The found member flags.</returns> public long DeserializeMembers(BsonDeserializationContext context, Action<string, long> memberHandler) { var reader = context.Reader; var foundMemberFlags = 0L; reader.ReadStartDocument(); while (reader.ReadBsonType() != 0) { var trieDecoder = new TrieNameDecoder<long>(_trie); var elementName = reader.ReadName(trieDecoder); long memberFlag; if (trieDecoder.Found) { memberFlag = trieDecoder.Value; } else { if (_extraMemberFlag == 0) { throw new BsonSerializationException(string.Format( "Invalid element: '{0}'.", elementName)); } else { memberFlag = _extraMemberFlag; } } memberHandler(elementName, memberFlag); foundMemberFlags |= memberFlag; } reader.ReadEndDocument(); var missingRequiredMemberFlags = _requiredMemberFlags & ~foundMemberFlags; if (missingRequiredMemberFlags != 0) { var missingRequiredMember = FindFirstMissingRequiredMember(missingRequiredMemberFlags); throw new BsonSerializationException(string.Format( "Missing element: '{0}'.", missingRequiredMember.ElementName)); } return foundMemberFlags; }