/// <summary> /// Serializes a value. /// </summary> /// <param name="context">The serialization context.</param> /// <param name="args">The serialization args.</param> /// <param name="value">The object.</param> protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, BsonBinaryData value) { var bsonWriter = context.Writer; var subType = value.SubType; if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy) { var writerGuidRepresentation = bsonWriter.Settings.GuidRepresentation; if (writerGuidRepresentation != GuidRepresentation.Unspecified) { var bytes = value.Bytes; var guidRepresentation = value.GuidRepresentation; if (guidRepresentation == GuidRepresentation.Unspecified) { var message = string.Format( "Cannot serialize BsonBinaryData with GuidRepresentation Unspecified to destination with GuidRepresentation {0}.", writerGuidRepresentation); throw new BsonSerializationException(message); } if (guidRepresentation != writerGuidRepresentation) { var guid = GuidConverter.FromBytes(bytes, guidRepresentation); bytes = GuidConverter.ToBytes(guid, writerGuidRepresentation); subType = (writerGuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy; guidRepresentation = writerGuidRepresentation; value = new BsonBinaryData(bytes, subType, guidRepresentation); } } } bsonWriter.WriteBinaryData(value); }
public void Deserialize_binary_data_should_return_expected_result_when_guid_representation_is_specified( [ClassValues(typeof(GuidModeValues))] GuidMode mode, [Values(-1, GuidRepresentation.Unspecified)] GuidRepresentation readerGuidRepresentation, [Values(GuidRepresentation.CSharpLegacy, GuidRepresentation.JavaLegacy, GuidRepresentation.PythonLegacy, GuidRepresentation.Standard)] GuidRepresentation guidRepresentation) { #pragma warning disable 618 mode.Set(); var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object)); var subject = new ObjectSerializer(discriminatorConvention, guidRepresentation); var bytes = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 }; var subType = GuidConverter.GetSubType(guidRepresentation); bytes[11] = (byte)subType; var readerSettings = new BsonBinaryReaderSettings(); if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2) { readerSettings.GuidRepresentation = readerGuidRepresentation == (GuidRepresentation)(-1) ? guidRepresentation : GuidRepresentation.Unspecified; } using (var memoryStream = new MemoryStream(bytes)) using (var reader = new BsonBinaryReader(memoryStream, readerSettings)) { var context = BsonDeserializationContext.CreateRoot(reader); reader.ReadStartDocument(); reader.ReadName("x"); var result = subject.Deserialize <object>(context); var guidBytes = bytes.Skip(12).Take(16).ToArray(); var expectedResult = GuidConverter.FromBytes(guidBytes, guidRepresentation); result.Should().Be(expectedResult); } #pragma warning restore 618 }
public void Deserializer_should_return_expected_result_when_representation_is_binary( GuidRepresentationMode defaultGuidRepresentationMode, GuidRepresentation defaultGuidRepresentation, GuidRepresentation serializerGuidRepresentation, GuidRepresentation readerGuidRepresentation, GuidRepresentation expectedGuidRepresentation) { GuidMode.Set(defaultGuidRepresentationMode, defaultGuidRepresentation); var subject = new GuidSerializer(serializerGuidRepresentation); var documentBytes = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 }; var documentSubType = GuidConverter.GetSubType(expectedGuidRepresentation); documentBytes[11] = (byte)documentSubType; var readerSettings = new BsonBinaryReaderSettings(); if (defaultGuidRepresentationMode == GuidRepresentationMode.V2) { #pragma warning disable 618 readerSettings.GuidRepresentation = readerGuidRepresentation; #pragma warning restore 618 } var reader = new BsonBinaryReader(new MemoryStream(documentBytes), readerSettings); reader.ReadStartDocument(); reader.ReadName("x"); var context = BsonDeserializationContext.CreateRoot(reader); var args = new BsonDeserializationArgs(); var result = subject.Deserialize(context, args); var guidBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; var expectedGuid = GuidConverter.FromBytes(guidBytes, expectedGuidRepresentation); result.Should().Be(expectedGuid); }
// public methods /// <summary> /// Deserializes a value. /// </summary> /// <param name="context">The deserialization context.</param> /// <param name="args">The deserialization args.</param> /// <returns>A deserialized value.</returns> public override Guid Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; string message; var bsonType = bsonReader.GetCurrentBsonType(); switch (bsonType) { case BsonType.Binary: #pragma warning disable 618 BsonBinaryData binaryData; if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && _guidRepresentation == GuidRepresentation.Unspecified) { binaryData = bsonReader.ReadBinaryData(); } else { binaryData = bsonReader.ReadBinaryDataWithGuidRepresentationUnspecified(); } var bytes = binaryData.Bytes; var subType = binaryData.SubType; var guidRepresentation = _guidRepresentation; if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && guidRepresentation == GuidRepresentation.Unspecified) { guidRepresentation = binaryData.GuidRepresentation; } if (bytes.Length != 16) { message = string.Format("Expected length to be 16, not {0}.", bytes.Length); throw new FormatException(message); } if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy) { message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType); throw new FormatException(message); } if (guidRepresentation == GuidRepresentation.Unspecified) { throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified."); } if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V3 || _guidRepresentation != GuidRepresentation.Unspecified) { var expectedSubType = GuidConverter.GetSubType(guidRepresentation); if (subType != expectedSubType) { throw new FormatException($"GuidSerializer cannot deserialize a Guid when GuidRepresentation is {guidRepresentation} and binary sub type is {subType}."); } } return(GuidConverter.FromBytes(bytes, guidRepresentation)); #pragma warning restore 618 case BsonType.String: return(new Guid(bsonReader.ReadString())); default: throw CreateCannotDeserializeFromBsonTypeException(bsonType); } }
private string GuidToString(BsonBinarySubType subType, byte[] bytes, GuidRepresentation guidRepresentation) { if (bytes.Length != 16) { var message = string.Format("Length of binary subtype {0} must be 16, not {1}.", subType, bytes.Length); throw new ArgumentException(message); } if (subType == BsonBinarySubType.UuidLegacy) { if (guidRepresentation == GuidRepresentation.Standard) { throw new ArgumentException("GuidRepresentation for binary subtype UuidLegacy must not be Standard."); } } if (subType == BsonBinarySubType.UuidStandard) { if (guidRepresentation == GuidRepresentation.Unspecified) { guidRepresentation = GuidRepresentation.Standard; } if (guidRepresentation != GuidRepresentation.Standard) { var message = string.Format("GuidRepresentation for binary subtype UuidStandard must be Standard, not {0}.", guidRepresentation); throw new ArgumentException(message); } } if (guidRepresentation == GuidRepresentation.Unspecified) { var s = BsonUtils.ToHexString(bytes); var parts = new string[] { s.Substring(0, 8), s.Substring(8, 4), s.Substring(12, 4), s.Substring(16, 4), s.Substring(20, 12) }; return(string.Format("HexData({0}, \"{1}\")", (int)subType, string.Join("-", parts))); } else { string uuidConstructorName; switch (guidRepresentation) { case GuidRepresentation.CSharpLegacy: uuidConstructorName = "CSUUID"; break; case GuidRepresentation.JavaLegacy: uuidConstructorName = "JUUID"; break; case GuidRepresentation.PythonLegacy: uuidConstructorName = "PYUUID"; break; case GuidRepresentation.Standard: uuidConstructorName = "UUID"; break; default: throw new BsonInternalException("Unexpected GuidRepresentation"); } var guid = GuidConverter.FromBytes(bytes, guidRepresentation); return(string.Format("{0}(\"{1}\")", uuidConstructorName, guid.ToString())); } }
private Guid UnwrapKeyId(RawBsonDocument wrappedKeyDocument) { var keyId = wrappedKeyDocument["_id"].AsBsonBinaryData; if (keyId.SubType != BsonBinarySubType.UuidStandard) { throw new InvalidOperationException($"KeyId sub type must be UuidStandard, not: {keyId.SubType}."); } return(GuidConverter.FromBytes(keyId.Bytes, GuidRepresentation.Standard)); }
/// <summary> /// Deserializes an object from a BsonReader. /// </summary> /// <param name="bsonReader">The BsonReader.</param> /// <param name="nominalType">The nominal type of the object.</param> /// <param name="options">The serialization options.</param> /// <returns>An object.</returns> public override object Deserialize( BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options ) { var bsonType = bsonReader.CurrentBsonType; string message; switch (bsonType) { case BsonType.Binary: byte[] bytes; BsonBinarySubType subType; bsonReader.ReadBinaryData(out bytes, out subType); if (bytes.Length != 16) { message = string.Format("Expected length to be 16, not {0}.", bytes.Length); throw new FileFormatException(message); } if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy) { message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType); throw new FileFormatException(message); } if (bsonReader.GuidRepresentation == GuidRepresentation.Unspecified) { throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified."); } var expectedSubType = (bsonReader.GuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy; if (subType != expectedSubType) { message = string.Format("Expected binary sub type {0}, not {1}, for GuidRepresentation {2}.", expectedSubType, subType, bsonReader.GuidRepresentation); throw new FileFormatException(message); } return(GuidConverter.FromBytes(bytes, bsonReader.GuidRepresentation)); case BsonType.String: return(new Guid(bsonReader.ReadString())); default: message = string.Format("Cannot deserialize Guid from BsonType {0}.", bsonType); throw new FileFormatException(message); } }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { throw new ArgumentNullException("value"); } var binaryData = (BsonBinaryData)value; var subType = binaryData.SubType; if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy) { var writerGuidRepresentation = bsonWriter.Settings.GuidRepresentation; if (writerGuidRepresentation != GuidRepresentation.Unspecified) { var bytes = binaryData.Bytes; var guidRepresentation = binaryData.GuidRepresentation; if (guidRepresentation == GuidRepresentation.Unspecified) { var message = string.Format( "Cannot serialize BsonBinaryData with GuidRepresentation Unspecified to destination with GuidRepresentation {0}.", writerGuidRepresentation); throw new BsonSerializationException(message); } if (guidRepresentation != writerGuidRepresentation) { var guid = GuidConverter.FromBytes(bytes, guidRepresentation); bytes = GuidConverter.ToBytes(guid, writerGuidRepresentation); subType = (writerGuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy; guidRepresentation = writerGuidRepresentation; binaryData = new BsonBinaryData(bytes, subType, guidRepresentation); } } } bsonWriter.WriteBinaryData(binaryData); }
// public methods /// <summary> /// Deserializes an object from a BsonReader. /// </summary> /// <param name="bsonReader">The BsonReader.</param> /// <param name="nominalType">The nominal type of the object.</param> /// <param name="actualType">The actual type of the object.</param> /// <param name="options">The serialization options.</param> /// <returns>An object.</returns> public override object Deserialize( BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) { VerifyTypes(nominalType, actualType, typeof(Guid)); var bsonType = bsonReader.GetCurrentBsonType(); string message; switch (bsonType) { case BsonType.Binary: var binaryData = bsonReader.ReadBinaryData(); var bytes = binaryData.Bytes; var subType = binaryData.SubType; var guidRepresentation = binaryData.GuidRepresentation; if (bytes.Length != 16) { message = string.Format("Expected length to be 16, not {0}.", bytes.Length); throw new FileFormatException(message); } if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy) { message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType); throw new FileFormatException(message); } if (guidRepresentation == GuidRepresentation.Unspecified) { throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified."); } return(GuidConverter.FromBytes(bytes, guidRepresentation)); case BsonType.String: return(new Guid(bsonReader.ReadString())); default: message = string.Format("Cannot deserialize Guid from BsonType {0}.", bsonType); throw new FileFormatException(message); } }
public void ExternalKeyVaultTest( [Values(false, true)] bool withExternalKeyVault, [Values(false, true)] bool async) { RequireServer.Check().Supports(Feature.ClientSideEncryption); var clientEncryptedSchema = new BsonDocument("db.coll", JsonFileReader.Instance.Documents["external.external-schema.json"]); using (var client = ConfigureClient()) using (var clientEncrypted = ConfigureClientEncrypted(clientEncryptedSchema, withExternalKeyVault)) using (var clientEncryption = ConfigureClientEncryption(clientEncrypted.Wrapped as MongoClient)) { var datakeys = GetCollection(client, __keyVaultCollectionNamespace); var externalKey = JsonFileReader.Instance.Documents["external.external-key.json"]; Insert(datakeys, async, externalKey); var coll = GetCollection(clientEncrypted, __collCollectionNamespace); var exception = Record.Exception(() => Insert(coll, async, new BsonDocument("encrypted", "test"))); if (withExternalKeyVault) { exception.InnerException.Should().BeOfType <MongoAuthenticationException>(); } else { exception.Should().BeNull(); } var encryptionOptions = new EncryptOptions( algorithm: EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(), keyId: GuidConverter.FromBytes(Convert.FromBase64String("LOCALAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard)); exception = Record.Exception(() => ExplicitEncrypt(clientEncryption, encryptionOptions, "test", async)); if (withExternalKeyVault) { exception.InnerException.Should().BeOfType <MongoAuthenticationException>(); } else { exception.Should().BeNull(); } } }
// public methods /// <summary> /// Deserializes a value. /// </summary> /// <param name="context">The deserialization context.</param> /// <param name="args">The deserialization args.</param> /// <returns>A deserialized value.</returns> public override Guid Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; string message; var bsonType = bsonReader.GetCurrentBsonType(); switch (bsonType) { case BsonType.Binary: var binaryData = bsonReader.ReadBinaryData(); var bytes = binaryData.Bytes; var subType = binaryData.SubType; var guidRepresentation = binaryData.GuidRepresentation; if (bytes.Length != 16) { message = string.Format("Expected length to be 16, not {0}.", bytes.Length); throw new FormatException(message); } if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy) { message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType); throw new FormatException(message); } if (guidRepresentation == GuidRepresentation.Unspecified) { throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified."); } return(GuidConverter.FromBytes(bytes, guidRepresentation)); case BsonType.String: return(new Guid(bsonReader.ReadString())); default: throw CreateCannotDeserializeFromBsonTypeException(bsonType); } }
public void CorpusTest( [Values(false, true)] bool useLocalSchema, [Values(false, true)] bool async) { RequireServer.Check().Supports(Feature.ClientSideEncryption); var corpusSchema = JsonFileReader.Instance.Documents["corpus.corpus-schema.json"]; var schemaMap = useLocalSchema ? new BsonDocument("db.coll", corpusSchema) : null; using (var client = ConfigureClient()) using (var clientEncrypted = ConfigureClientEncrypted(schemaMap)) using (var clientEncryption = ConfigureClientEncryption(clientEncrypted.Wrapped as MongoClient)) { CreateCollection(client, __collCollectionNamespace, new BsonDocument("$jsonSchema", corpusSchema)); var corpusKeyLocal = JsonFileReader.Instance.Documents["corpus.corpus-key-local.json"]; var corpusKeyAws = JsonFileReader.Instance.Documents["corpus.corpus-key-aws.json"]; var keyVaultCollection = GetCollection(client, __keyVaultCollectionNamespace); Insert(keyVaultCollection, async, corpusKeyLocal, corpusKeyAws); var corpus = JsonFileReader.Instance.Documents["corpus.corpus.json"]; var corpusCopied = new BsonDocument { corpus.GetElement("_id"), corpus.GetElement("altname_aws"), corpus.GetElement("altname_local") }; foreach (var corpusElement in corpus.Elements.Where(c => c.Value.IsBsonDocument)) { var corpusValue = corpusElement.Value.DeepClone(); var kms = corpusValue["kms"].AsString; var abbreviatedAlgorithmName = corpusValue["algo"].AsString; var identifier = corpusValue["identifier"].AsString; var allowed = corpusValue["allowed"].ToBoolean(); var value = corpusValue["value"]; var method = corpusValue["method"].AsString; switch (method) { case "auto": corpusCopied.Add(corpusElement); continue; case "explicit": { var encryptionOptions = CreateEncryptOptions(abbreviatedAlgorithmName, identifier, kms); BsonBinaryData encrypted = null; var exception = Record.Exception(() => { encrypted = ExplicitEncrypt( clientEncryption, encryptionOptions, value, async); }); if (allowed) { exception.Should().BeNull(); encrypted.Should().NotBeNull(); corpusValue["value"] = encrypted; } else { exception.Should().NotBeNull(); } corpusCopied.Add(new BsonElement(corpusElement.Name, corpusValue)); } break; default: throw new ArgumentException($"Unsupported method name {method}.", nameof(method)); } } var coll = GetCollection(clientEncrypted, __collCollectionNamespace); Insert(coll, async, corpusCopied); var corpusDecrypted = Find(coll, new BsonDocument(), async).Single(); corpusDecrypted.Should().Be(corpus); var corpusEncryptedExpected = JsonFileReader.Instance.Documents["corpus.corpus-encrypted.json"]; coll = GetCollection(client, __collCollectionNamespace); var corpusEncryptedActual = Find(coll, new BsonDocument(), async).Single(); foreach (var expectedElement in corpusEncryptedExpected.Elements.Where(c => c.Value.IsBsonDocument)) { var expectedElementValue = expectedElement.Value; var expectedAlgorithm = ParseAlgorithm(expectedElementValue["algo"].AsString); var expectedAllowed = expectedElementValue["allowed"].ToBoolean(); var expectedValue = expectedElementValue["value"]; var actualValue = corpusEncryptedActual.GetValue(expectedElement.Name)["value"]; switch (expectedAlgorithm) { case EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic: actualValue.Should().Be(expectedValue); break; case EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random: if (expectedAllowed) { actualValue.Should().NotBe(expectedValue); } break; default: throw new ArgumentException($"Unsupported expected algorithm {expectedAllowed}.", nameof(expectedAlgorithm)); } if (expectedAllowed) { var actualDecryptedValue = ExplicitDecrypt(clientEncryption, actualValue.AsBsonBinaryData, async); var expectedDecryptedValue = ExplicitDecrypt(clientEncryption, expectedValue.AsBsonBinaryData, async); actualDecryptedValue.Should().Be(expectedDecryptedValue); } else { actualValue.Should().Be(expectedValue); } } } EncryptOptions CreateEncryptOptions(string algorithm, string identifier, string kms) { Guid? keyId = null; string alternateName = null; if (identifier == "id") { switch (kms) { case "local": keyId = GuidConverter.FromBytes(Convert.FromBase64String("LOCALAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard); break; case "aws": keyId = GuidConverter.FromBytes(Convert.FromBase64String("AWSAAAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard); break; default: throw new ArgumentException($"Unsupported kms type {kms}."); } } else if (identifier == "altname") { alternateName = kms; } else { throw new ArgumentException($"Unsupported identifier {identifier}.", nameof(identifier)); } return(new EncryptOptions(ParseAlgorithm(algorithm).ToString(), alternateName, keyId)); } EncryptionAlgorithm ParseAlgorithm(string algorithm) { switch (algorithm) { case "rand": return(EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random); case "det": return(EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic); default: throw new ArgumentException($"Unsupported algorithm {algorithm}."); } } }
// private methods private void ReadValue() { object jsonDotNetValue; switch (_wrappedReader.GetCurrentBsonType()) { case BsonType.Array: _wrappedReader.ReadStartArray(); SetCurrentToken(Newtonsoft.Json.JsonToken.StartArray); return; case BsonType.Binary: var bsonBinaryData = _wrappedReader.ReadBinaryData(); switch (bsonBinaryData.SubType) { case BsonBinarySubType.UuidLegacy: var guidRepresentation = GuidRepresentation.Unspecified; var bsonReader = _wrappedReader as BsonReader; if (bsonReader != null) { guidRepresentation = bsonReader.Settings.GuidRepresentation; } jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, guidRepresentation); break; case BsonBinarySubType.UuidStandard: jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, GuidRepresentation.Standard); break; default: jsonDotNetValue = bsonBinaryData.Bytes; break; } SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, jsonDotNetValue, bsonBinaryData); return; case BsonType.Boolean: var booleanValue = _wrappedReader.ReadBoolean(); SetCurrentToken(Newtonsoft.Json.JsonToken.Boolean, booleanValue, (BsonBoolean)booleanValue); return; case BsonType.DateTime: var bsonDateTime = new BsonDateTime(_wrappedReader.ReadDateTime()); if (bsonDateTime.IsValidDateTime) { jsonDotNetValue = bsonDateTime.ToUniversalTime(); } else { jsonDotNetValue = bsonDateTime.MillisecondsSinceEpoch; } SetCurrentToken(Newtonsoft.Json.JsonToken.Date, jsonDotNetValue, bsonDateTime); return; case BsonType.Document: _wrappedReader.ReadStartDocument(); SetCurrentToken(Newtonsoft.Json.JsonToken.StartObject); return; case BsonType.Double: var bsonDouble = new BsonDouble(_wrappedReader.ReadDouble()); switch (FloatParseHandling) { case Newtonsoft.Json.FloatParseHandling.Decimal: jsonDotNetValue = Convert.ToDecimal(bsonDouble); break; case Newtonsoft.Json.FloatParseHandling.Double: jsonDotNetValue = bsonDouble.Value; break; default: throw new NotSupportedException(string.Format("Unexpected FloatParseHandling value: {0}.", FloatParseHandling)); } SetCurrentToken(Newtonsoft.Json.JsonToken.Float, jsonDotNetValue, bsonDouble); return; case BsonType.Int32: var bsonInt32 = (BsonInt32)_wrappedReader.ReadInt32(); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, (long)bsonInt32.Value, bsonInt32); return; case BsonType.Int64: var bsonInt64 = (BsonInt64)_wrappedReader.ReadInt64(); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonInt64.Value, bsonInt64); return; case BsonType.JavaScript: { var code = _wrappedReader.ReadJavaScript(); var bsonJavaScript = new BsonJavaScript(code); SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScript); } return; case BsonType.JavaScriptWithScope: { var code = _wrappedReader.ReadJavaScriptWithScope(); var context = BsonDeserializationContext.CreateRoot(_wrappedReader); var scope = BsonDocumentSerializer.Instance.Deserialize <BsonDocument>(context); var bsonJavaScriptWithScope = new BsonJavaScriptWithScope(code, scope); SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScriptWithScope); } return; case BsonType.MaxKey: _wrappedReader.ReadMaxKey(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMaxKey.Value); return; case BsonType.MinKey: _wrappedReader.ReadMinKey(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMinKey.Value); return; case BsonType.Null: _wrappedReader.ReadNull(); SetCurrentToken(Newtonsoft.Json.JsonToken.Null, null, BsonNull.Value); return; case BsonType.ObjectId: var bsonObjectId = new BsonObjectId(_wrappedReader.ReadObjectId()); SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, bsonObjectId.Value.ToByteArray(), bsonObjectId); return; case BsonType.RegularExpression: var bsonRegularExpression = _wrappedReader.ReadRegularExpression(); var pattern = bsonRegularExpression.Pattern; var options = bsonRegularExpression.Options; jsonDotNetValue = "/" + pattern.Replace("/", "\\/") + "/" + options; SetCurrentToken(Newtonsoft.Json.JsonToken.String, jsonDotNetValue, bsonRegularExpression); return; case BsonType.String: var stringValue = _wrappedReader.ReadString(); SetCurrentToken(Newtonsoft.Json.JsonToken.String, stringValue, (BsonString)stringValue); return; case BsonType.Symbol: var bsonSymbol = BsonSymbolTable.Lookup(_wrappedReader.ReadSymbol()); SetCurrentToken(Newtonsoft.Json.JsonToken.String, bsonSymbol.Name, bsonSymbol); return; case BsonType.Timestamp: var bsonTimestamp = new BsonTimestamp(_wrappedReader.ReadTimestamp()); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonTimestamp.Value, bsonTimestamp); return; case BsonType.Undefined: _wrappedReader.ReadUndefined(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonUndefined.Value); return; default: var message = string.Format("Unexpected BsonType: {0}.", _wrappedReader.GetCurrentBsonType()); throw new Newtonsoft.Json.JsonReaderException(message); } }
/// <summary> /// Writes BSON binary data to the writer. /// </summary> /// <param name="bytes">The binary data.</param> /// <param name="subType">The binary data subtype.</param> /// <param name="guidRepresentation">The representation for Guids.</param> public override void WriteBinaryData( byte[] bytes, BsonBinarySubType subType, GuidRepresentation guidRepresentation) { if (Disposed) { throw new ObjectDisposedException("JsonWriter"); } if (State != BsonWriterState.Value && State != BsonWriterState.Initial) { ThrowInvalidState("WriteBinaryData", BsonWriterState.Value, BsonWriterState.Initial); } if (_jsonWriterSettings.OutputMode == JsonOutputMode.Shell) { WriteNameHelper(Name); switch (subType) { case BsonBinarySubType.UuidLegacy: case BsonBinarySubType.UuidStandard: if (bytes.Length != 16) { var message = string.Format("Length of binary subtype {0} must be 16, not {1}.", subType, bytes.Length); throw new ArgumentException(message); } if (subType == BsonBinarySubType.UuidLegacy && guidRepresentation == GuidRepresentation.Standard) { throw new ArgumentException("GuidRepresentation for binary subtype UuidLegacy must not be Standard."); } if (subType == BsonBinarySubType.UuidStandard && guidRepresentation != GuidRepresentation.Standard) { var message = string.Format("GuidRepresentation for binary subtype UuidStandard must be Standard, not {0}.", guidRepresentation); throw new ArgumentException(message); } if (_jsonWriterSettings.ShellVersion >= new Version(2, 0, 0)) { if (guidRepresentation == GuidRepresentation.Unspecified) { var s = BsonUtils.ToHexString(bytes); var parts = new string[] { s.Substring(0, 8), s.Substring(8, 4), s.Substring(12, 4), s.Substring(16, 4), s.Substring(20, 12) }; _textWriter.Write("HexData({0}, \"{1}\")", (int)subType, string.Join("-", parts)); } else { string uuidConstructorName; switch (guidRepresentation) { case GuidRepresentation.CSharpLegacy: uuidConstructorName = "CSUUID"; break; case GuidRepresentation.JavaLegacy: uuidConstructorName = "JUUID"; break; case GuidRepresentation.PythonLegacy: uuidConstructorName = "PYUUID"; break; case GuidRepresentation.Standard: uuidConstructorName = "UUID"; break; default: throw new BsonInternalException("Unexpected GuidRepresentation"); } var guid = GuidConverter.FromBytes(bytes, guidRepresentation); _textWriter.Write("{0}(\"{1}\")", uuidConstructorName, guid.ToString()); } } else { _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes)); } break; default: _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes)); break; } } else { WriteStartDocument(); WriteString("$binary", Convert.ToBase64String(bytes)); WriteString("$type", ((int)subType).ToString("x2")); WriteEndDocument(); } State = GetNextState(); }
public void SerializeValue_should_convert_representation_when_required( [ClassValues(typeof(GuidModeValues))] GuidMode mode, [Values( GuidRepresentation.CSharpLegacy, GuidRepresentation.JavaLegacy, GuidRepresentation.PythonLegacy, GuidRepresentation.Standard, GuidRepresentation.Unspecified)] GuidRepresentation writerGuidRepresentation, [Values( GuidRepresentation.CSharpLegacy, GuidRepresentation.JavaLegacy, GuidRepresentation.PythonLegacy, GuidRepresentation.Standard, GuidRepresentation.Unspecified)] GuidRepresentation valueGuidRepresentation) { mode.Set(); #pragma warning disable 618 var subject = new BsonBinaryDataSerializer(); var mockWriter = new Mock <IBsonWriter>(); var writerSettings = new BsonBinaryWriterSettings(); if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2) { writerSettings.GuidRepresentation = writerGuidRepresentation; } mockWriter.SetupGet(m => m.Settings).Returns(writerSettings); var context = BsonSerializationContext.CreateRoot(mockWriter.Object); var args = new BsonSerializationArgs(); var bytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; var subType = valueGuidRepresentation == GuidRepresentation.Unspecified ? BsonBinarySubType.UuidLegacy : GuidConverter.GetSubType(valueGuidRepresentation); var value = BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 ? new BsonBinaryData(bytes, subType, valueGuidRepresentation) : new BsonBinaryData(bytes, subType); var isExceptionExpected = BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && writerGuidRepresentation != GuidRepresentation.Unspecified && valueGuidRepresentation == GuidRepresentation.Unspecified; if (!isExceptionExpected) { subject.Serialize(context, args, value); var shouldConvertRepresentation = BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && writerGuidRepresentation != GuidRepresentation.Unspecified && valueGuidRepresentation != GuidRepresentation.Unspecified && valueGuidRepresentation != writerGuidRepresentation; var writtenValue = value; if (shouldConvertRepresentation) { var guid = GuidConverter.FromBytes(bytes, valueGuidRepresentation); var convertedBytes = GuidConverter.ToBytes(guid, writerGuidRepresentation); var convertedSubType = GuidConverter.GetSubType(writerGuidRepresentation); writtenValue = new BsonBinaryData(convertedBytes, convertedSubType, writerGuidRepresentation); } mockWriter.Verify(m => m.WriteBinaryData(writtenValue), Times.Once); } #pragma warning restore 618 }