diff --git a/src/MongoDB.Bson/IO/BsonBinaryReader.cs b/src/MongoDB.Bson/IO/BsonBinaryReader.cs
index 00d59205b67..f054850350e 100644
--- a/src/MongoDB.Bson/IO/BsonBinaryReader.cs
+++ b/src/MongoDB.Bson/IO/BsonBinaryReader.cs
@@ -273,8 +273,34 @@ public override byte[] ReadBytes()
State = GetNextState();
return _bsonStream.ReadBytes(size);
}
-#pragma warning restore 618
+ ///
+ /// Reads BSON binary data from the reader to the buffer at offset and respecting the size.
+ ///
+ /// Target buffer
+ /// Target offset
+ /// Bytes read
+ public override int ReadBytes(byte[] bytes, int offset) {
+ if (Disposed) { ThrowObjectDisposedException(); }
+ VerifyBsonType("ReadBytes", BsonType.Binary);
+
+ int size = ReadSize();
+
+ var subType = _bsonStream.ReadBinarySubType();
+ if (subType != BsonBinarySubType.Binary)
+ {
+ var message = string.Format("ReadBytes requires the binary sub type to be Binary, not {0}.", subType);
+ throw new FormatException(message);
+ }
+
+ State = GetNextState();
+
+ _bsonStream.ReadBytes(bytes, offset, size);
+
+ return size;
+ }
+
+#pragma warning restore 618
///
/// Reads a BSON DateTime from the reader.
///
diff --git a/src/MongoDB.Bson/IO/BsonBinaryWriter.cs b/src/MongoDB.Bson/IO/BsonBinaryWriter.cs
index 8a322f9fe80..9103fe57de6 100644
--- a/src/MongoDB.Bson/IO/BsonBinaryWriter.cs
+++ b/src/MongoDB.Bson/IO/BsonBinaryWriter.cs
@@ -261,6 +261,28 @@ public override void WriteBytes(byte[] bytes)
State = GetNextState();
}
+ ///
+ /// Writes BSON binary data to the writer.
+ ///
+ /// The bytes.
+ /// The count of bytes used in the bytes[]
+ public override void WriteBytes(byte[] bytes, int size)
+ {
+ if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+ if (State != BsonWriterState.Value)
+ {
+ ThrowInvalidState("WriteBytes", BsonWriterState.Value);
+ }
+
+ _bsonStream.WriteBsonType(BsonType.Binary);
+ WriteNameHelper();
+ _bsonStream.WriteInt32(size);
+ _bsonStream.WriteBinarySubType(BsonBinarySubType.Binary);
+ _bsonStream.WriteBytes(bytes, 0, size);
+
+ State = GetNextState();
+ }
+
///
/// Writes a BSON DateTime to the writer.
///
diff --git a/src/MongoDB.Bson/IO/BsonDocumentReader.cs b/src/MongoDB.Bson/IO/BsonDocumentReader.cs
index aa4a1e93252..3868c897d5d 100644
--- a/src/MongoDB.Bson/IO/BsonDocumentReader.cs
+++ b/src/MongoDB.Bson/IO/BsonDocumentReader.cs
@@ -179,6 +179,32 @@ public override byte[] ReadBytes()
return binaryData.Bytes;
}
+
+ ///
+ /// Reads BSON binary data from the reader to the buffer at offset and respecting the size.
+ ///
+ /// Target buffer
+ /// Target offset
+ /// Bytes read
+ public override int ReadBytes(byte[] bytes, int offset = 0)
+ {
+ if (Disposed) { ThrowObjectDisposedException(); }
+ VerifyBsonType("ReadBytes", BsonType.Binary);
+
+ State = GetNextState();
+ var binaryData = _currentValue.AsBsonBinaryData;
+
+ var subType = binaryData.SubType;
+ if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
+ {
+ var message = string.Format("ReadBytes requires the binary sub type to be Binary, not {0}.", subType);
+ throw new FormatException(message);
+ }
+
+ binaryData.Bytes.CopyTo(bytes, offset);
+
+ return binaryData.Bytes.Length;
+ }
#pragma warning restore 618
///
diff --git a/src/MongoDB.Bson/IO/BsonDocumentWriter.cs b/src/MongoDB.Bson/IO/BsonDocumentWriter.cs
index 3f77160f1c2..cb9bcbfce09 100644
--- a/src/MongoDB.Bson/IO/BsonDocumentWriter.cs
+++ b/src/MongoDB.Bson/IO/BsonDocumentWriter.cs
@@ -133,6 +133,21 @@ public override void WriteBytes(byte[] bytes)
State = GetNextState();
}
+ ///
+ /// Writes BSON binary data to the writer.
+ ///
+ /// The bytes.
+ /// The count of bytes used in the bytes[]
+ public override void WriteBytes(byte[] bytes, int size) {
+ if (bytes.Length != size) {
+ // TODO: Better use a buffer manager here or Provide size in BsonBinaryData
+ var copy = new byte[size];
+ Buffer.BlockCopy(bytes, 0, copy, 0, size);
+ WriteBytes(copy);
+ } else
+ WriteBytes(bytes);
+ }
+
///
/// Writes a BSON DateTime to the writer.
///
diff --git a/src/MongoDB.Bson/IO/BsonReader.cs b/src/MongoDB.Bson/IO/BsonReader.cs
index 41222a3f4ff..c7a5e9995d4 100644
--- a/src/MongoDB.Bson/IO/BsonReader.cs
+++ b/src/MongoDB.Bson/IO/BsonReader.cs
@@ -167,6 +167,14 @@ public BsonType GetCurrentBsonType()
/// A byte array.
public abstract byte[] ReadBytes();
+ ///
+ /// Reads BSON binary data from the reader to the buffer at offset and respecting the size.
+ ///
+ /// Target buffer
+ /// Target offset
+ /// Bytes read
+ public abstract int ReadBytes(byte[] bytes, int offset = 0);
+
///
/// Reads a BSON DateTime from the reader.
///
diff --git a/src/MongoDB.Bson/IO/BsonWriter.cs b/src/MongoDB.Bson/IO/BsonWriter.cs
index 9941a9a0b09..3d49aaa3a47 100644
--- a/src/MongoDB.Bson/IO/BsonWriter.cs
+++ b/src/MongoDB.Bson/IO/BsonWriter.cs
@@ -184,6 +184,13 @@ public void PushSettings(Action configurator)
/// The bytes.
public abstract void WriteBytes(byte[] bytes);
+ ///
+ /// Writes BSON binary data to the writer.
+ ///
+ /// The bytes.
+ ///
+ public abstract void WriteBytes(byte[] bytes, int size);
+
///
/// Writes a BSON DateTime to the writer.
///
diff --git a/src/MongoDB.Bson/IO/IBsonReader.cs b/src/MongoDB.Bson/IO/IBsonReader.cs
index 541284dae7f..d434661352f 100644
--- a/src/MongoDB.Bson/IO/IBsonReader.cs
+++ b/src/MongoDB.Bson/IO/IBsonReader.cs
@@ -83,6 +83,14 @@ public interface IBsonReader : IDisposable
/// A byte array.
byte[] ReadBytes();
+ ///
+ /// Reads BSON binary data from the reader to the buffer at offset and respecting the size.
+ ///
+ /// Target buffer
+ /// Target offset
+ /// Bytes read
+ int ReadBytes(byte[] buffer, int offset);
+
///
/// Reads a BSON DateTime from the reader.
///
diff --git a/src/MongoDB.Bson/IO/IBsonWriter.cs b/src/MongoDB.Bson/IO/IBsonWriter.cs
index 70af5d2884e..e097fe85fa0 100644
--- a/src/MongoDB.Bson/IO/IBsonWriter.cs
+++ b/src/MongoDB.Bson/IO/IBsonWriter.cs
@@ -101,6 +101,13 @@ public interface IBsonWriter : IDisposable
/// The bytes.
void WriteBytes(byte[] bytes);
+ ///
+ /// Writes BSON binary data to the writer.
+ ///
+ /// The bytes.
+ ///
+ void WriteBytes(byte[] bytes, int size);
+
///
/// Writes a BSON DateTime to the writer.
///
diff --git a/src/MongoDB.Bson/IO/JsonReader.cs b/src/MongoDB.Bson/IO/JsonReader.cs
index a464d556571..1ca725fbb28 100644
--- a/src/MongoDB.Bson/IO/JsonReader.cs
+++ b/src/MongoDB.Bson/IO/JsonReader.cs
@@ -421,6 +421,33 @@ public override byte[] ReadBytes()
}
return binaryData.Bytes;
+
+ }
+
+ ///
+ /// Reads BSON binary data from the reader to the buffer at offset and respecting the size.
+ ///
+ /// Target buffer
+ /// Target offset
+ /// Bytes read
+ public override int ReadBytes(byte[] bytes, int offset)
+ {
+
+ if (Disposed) { ThrowObjectDisposedException(); }
+ VerifyBsonType("ReadBinaryData", BsonType.Binary);
+ State = GetNextState();
+ var binaryData = _currentValue.AsBsonBinaryData;
+
+ var subType = binaryData.SubType;
+ if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
+ {
+ var message = string.Format("ReadBytes requires the binary sub type to be Binary, not {0}.", subType);
+ throw new FormatException(message);
+ }
+
+ binaryData.Bytes.CopyTo(bytes, offset);
+
+ return binaryData.Bytes.Length;
#pragma warning restore
}
diff --git a/src/MongoDB.Bson/IO/JsonToken.cs b/src/MongoDB.Bson/IO/JsonToken.cs
index afb527e62de..5446d63b94f 100644
--- a/src/MongoDB.Bson/IO/JsonToken.cs
+++ b/src/MongoDB.Bson/IO/JsonToken.cs
@@ -13,6 +13,9 @@
* limitations under the License.
*/
+
+
+
using System;
namespace MongoDB.Bson.IO
diff --git a/src/MongoDB.Bson/IO/JsonWriter.cs b/src/MongoDB.Bson/IO/JsonWriter.cs
index dc253e8e368..af1b35efbd4 100644
--- a/src/MongoDB.Bson/IO/JsonWriter.cs
+++ b/src/MongoDB.Bson/IO/JsonWriter.cs
@@ -175,6 +175,21 @@ public override void WriteBytes(byte[] bytes)
WriteBinaryData(new BsonBinaryData(bytes, BsonBinarySubType.Binary));
}
+ ///
+ /// Writes BSON binary data to the writer.
+ ///
+ /// The bytes.
+ /// The count of bytes used in the bytes[]
+ public override void WriteBytes(byte[] bytes, int size) {
+ if (bytes.Length != size) {
+ // TODO: Better use a buffer manager here or Provide size in BsonBinaryData
+ var copy = new byte[size];
+ Buffer.BlockCopy(bytes, 0, copy, 0, size);
+ WriteBytes(copy);
+ } else
+ WriteBytes(bytes);
+ }
+
///
/// Writes a BSON DateTime to the writer.
///
diff --git a/src/MongoDB.Bson/IO/WrappingBsonWriter.cs b/src/MongoDB.Bson/IO/WrappingBsonWriter.cs
index 53104f735c1..a282dde9a20 100644
--- a/src/MongoDB.Bson/IO/WrappingBsonWriter.cs
+++ b/src/MongoDB.Bson/IO/WrappingBsonWriter.cs
@@ -168,6 +168,13 @@ public virtual void WriteBytes(byte[] bytes)
_wrapped.WriteBytes(bytes);
}
+ ///
+ public virtual void WriteBytes(byte[] bytes, int size)
+ {
+ ThrowIfDisposed();
+ _wrapped.WriteBytes(bytes, size);
+ }
+
///
public virtual void WriteDateTime(long value)
{
diff --git a/src/MongoDB.Driver/Linq/Processors/Pipeline/MethodCallBinders/JoinSerializer.cs b/src/MongoDB.Driver/Linq/Processors/Pipeline/MethodCallBinders/JoinSerializer.cs
index 96c430625f2..0331a7d6fd0 100644
--- a/src/MongoDB.Driver/Linq/Processors/Pipeline/MethodCallBinders/JoinSerializer.cs
+++ b/src/MongoDB.Driver/Linq/Processors/Pipeline/MethodCallBinders/JoinSerializer.cs
@@ -188,6 +188,11 @@ public byte[] ReadBytes()
return _parent.ReadBytes();
}
+ public int ReadBytes(byte[] bytes, int offset = 0)
+ {
+ return _parent.ReadBytes(bytes, offset);
+ }
+
public long ReadDateTime()
{
return _parent.ReadDateTime();
diff --git a/tests/MongoDB.Bson.Tests/IO/JsonReaderTests.cs b/tests/MongoDB.Bson.Tests/IO/JsonReaderTests.cs
index 77da4d7ad09..f889fc13cc1 100644
--- a/tests/MongoDB.Bson.Tests/IO/JsonReaderTests.cs
+++ b/tests/MongoDB.Bson.Tests/IO/JsonReaderTests.cs
@@ -916,6 +916,23 @@ public void TestObjectIdStrict()
Assert.Equal(json, BsonSerializer.Deserialize(json).ToJson(jsonSettings));
}
+ [Fact]
+ public void TestReadWithReusedBuffer() {
+ var expectedBytes = new byte[] { 0x01, 0x23 };
+ var json = "HexData(0, \"123\")";
+ using (_bsonReader = new JsonReader(json))
+ {
+ Assert.Equal(BsonType.Binary, _bsonReader.ReadBsonType());
+ var bytes = new byte[1024];
+ int readBytes = _bsonReader.ReadBytes(bytes, 50);
+ Assert.Equal(2, readBytes);
+ Assert.True(expectedBytes.SequenceEqual(bytes.Skip(50).Take(2)));
+ Assert.Equal(BsonReaderState.Initial, _bsonReader.State);
+ }
+ var expectedJson = "new BinData(0, \"ASM=\")";
+ Assert.Equal(expectedJson, BsonSerializer.Deserialize(json).ToJson());
+ }
+
[Theory]
[InlineData("{ $regex : \"abc\", $options : \"i\" }", "abc", "i")]
[InlineData("{ $regex : \"abc/\", $options : \"i\" }", "abc/", "i")]
diff --git a/tests/MongoDB.Bson.Tests/IO/WrappingBsonWriterTests.cs b/tests/MongoDB.Bson.Tests/IO/WrappingBsonWriterTests.cs
index 1bc534b5e47..ef3e6c0bb45 100644
--- a/tests/MongoDB.Bson.Tests/IO/WrappingBsonWriterTests.cs
+++ b/tests/MongoDB.Bson.Tests/IO/WrappingBsonWriterTests.cs
@@ -368,6 +368,20 @@ public void WriteBytes_should_call_wrapped()
mockWrapped.Verify(m => m.WriteBytes(value), Times.Once);
}
+
+ [Fact]
+ public void WriteBytesPars_should_call_wrapped()
+ {
+ Mock mockWrapped;
+ var subject = CreateSubject(out mockWrapped);
+ const int size = 0;
+ var value = new byte[0];
+
+ subject.WriteBytes(value, size);
+
+ mockWrapped.Verify(m => m.WriteBytes(value, size), Times.Once);
+ }
+
[Fact]
public void WriteBytes_should_throw_when_disposed()
{