Skip to content

Commit a441495

Browse files
author
rstam
committed
CSHARP-666: Initial implementation of lazy and raw BsonDocument and BsonArray.
1 parent 25882b0 commit a441495

40 files changed

+6244
-867
lines changed

MongoDB.Bson/IO/BsonBinaryReader.cs

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.IO;
1718

1819
namespace MongoDB.Bson.IO
@@ -35,18 +36,35 @@ public class BsonBinaryReader : BsonReader
3536
/// <param name="buffer">A BsonBuffer.</param>
3637
/// <param name="settings">A BsonBinaryReaderSettings.</param>
3738
public BsonBinaryReader(BsonBuffer buffer, BsonBinaryReaderSettings settings)
39+
: this(buffer ?? new BsonBuffer(), buffer == null, settings)
40+
{
41+
}
42+
43+
/// <summary>
44+
/// Initializes a new instance of the BsonBinaryReader class.
45+
/// </summary>
46+
/// <param name="buffer">A BsonBuffer.</param>
47+
/// <param name="disposeBuffer">if set to <c>true</c> this BsonBinaryReader will own the buffer and when Dispose is called the buffer will be Disposed also.</param>
48+
/// <param name="settings">A BsonBinaryReaderSettings.</param>
49+
/// <exception cref="System.ArgumentNullException">
50+
/// buffer
51+
/// or
52+
/// settings
53+
/// </exception>
54+
public BsonBinaryReader(BsonBuffer buffer, bool disposeBuffer, BsonBinaryReaderSettings settings)
3855
: base(settings)
3956
{
4057
if (buffer == null)
4158
{
42-
_buffer = new BsonBuffer();
43-
_disposeBuffer = true; // only call Dispose if we allocated the buffer
59+
throw new ArgumentNullException("buffer");
4460
}
45-
else
61+
if (settings == null)
4662
{
47-
_buffer = buffer;
48-
_disposeBuffer = false;
63+
throw new ArgumentNullException("settings");
4964
}
65+
66+
_buffer = buffer;
67+
_disposeBuffer = disposeBuffer;
5068
_binaryReaderSettings = settings; // already frozen by base class
5169
_context = new BsonBinaryReaderContext(null, ContextType.TopLevel, 0, 0);
5270
}
@@ -316,7 +334,7 @@ public override void ReadEndDocument()
316334
}
317335

318336
_context = _context.PopContext(_buffer.Position);
319-
if (_context != null && _context.ContextType == ContextType.JavaScriptWithScope)
337+
if (_context.ContextType == ContextType.JavaScriptWithScope)
320338
{
321339
_context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
322340
}
@@ -425,6 +443,64 @@ public override ObjectId ReadObjectId()
425443
return _buffer.ReadObjectId();
426444
}
427445

446+
/// <summary>
447+
/// Reads a raw BSON array.
448+
/// </summary>
449+
/// <returns>
450+
/// The raw BSON array.
451+
/// </returns>
452+
public override IByteBuffer ReadRawBsonArray()
453+
{
454+
if (Disposed) { ThrowObjectDisposedException(); }
455+
VerifyBsonType("ReadStartArray", BsonType.Array);
456+
457+
var position = _buffer.Position;
458+
var length = _buffer.ReadInt32();
459+
var slice = _buffer.ByteBuffer.GetSlice(position, length);
460+
_buffer.Position = position + length;
461+
462+
switch (_context.ContextType)
463+
{
464+
case ContextType.Array: State = BsonReaderState.Type; break;
465+
case ContextType.Document: State = BsonReaderState.Type; break;
466+
case ContextType.TopLevel: State = BsonReaderState.Done; break;
467+
default: throw new BsonInternalException("Unexpected ContextType.");
468+
}
469+
470+
return slice;
471+
}
472+
473+
/// <summary>
474+
/// Reads a raw BSON document.
475+
/// </summary>
476+
/// <returns>
477+
/// The raw BSON document.
478+
/// </returns>
479+
public override IByteBuffer ReadRawBsonDocument()
480+
{
481+
if (Disposed) { ThrowObjectDisposedException(); }
482+
VerifyBsonType("ReadRawBsonDocument", BsonType.Document);
483+
484+
var position = _buffer.Position;
485+
var length = _buffer.ReadInt32();
486+
var slice = _buffer.ByteBuffer.GetSlice(position, length);
487+
_buffer.Position = position + length;
488+
489+
if (_context.ContextType == ContextType.JavaScriptWithScope)
490+
{
491+
_context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
492+
}
493+
switch (_context.ContextType)
494+
{
495+
case ContextType.Array: State = BsonReaderState.Type; break;
496+
case ContextType.Document: State = BsonReaderState.Type; break;
497+
case ContextType.TopLevel: State = BsonReaderState.Done; break;
498+
default: throw new BsonInternalException("Unexpected ContextType.");
499+
}
500+
501+
return slice;
502+
}
503+
428504
/// <summary>
429505
/// Reads a BSON regular expression from the reader.
430506
/// </summary>
@@ -597,8 +673,8 @@ protected override void Dispose(bool disposing)
597673
if (_disposeBuffer)
598674
{
599675
_buffer.Dispose();
600-
_buffer = null;
601676
}
677+
_buffer = null;
602678
}
603679
catch { } // ignore exceptions
604680
}

MongoDB.Bson/IO/BsonBinaryWriter.cs

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,36 @@ public class BsonBinaryWriter : BsonWriter
3838
/// <param name="buffer">A BsonBuffer.</param>
3939
/// <param name="settings">Optional BsonBinaryWriter settings.</param>
4040
public BsonBinaryWriter(Stream stream, BsonBuffer buffer, BsonBinaryWriterSettings settings)
41-
: base(settings)
41+
: this(buffer ?? new BsonBuffer(), buffer == null, settings)
4242
{
4343
_stream = stream;
44+
}
45+
46+
/// <summary>
47+
/// Initializes a new instance of the BsonBinaryWriter class.
48+
/// </summary>
49+
/// <param name="buffer">A BsonBuffer.</param>
50+
/// <param name="disposeBuffer">if set to <c>true</c> this BsonBinaryReader will own the buffer and when Dispose is called the buffer will be Disposed also.</param>
51+
/// <param name="settings">Optional BsonBinaryWriter settings.</param>
52+
/// <exception cref="System.ArgumentNullException">
53+
/// encoder
54+
/// or
55+
/// settings
56+
/// </exception>
57+
public BsonBinaryWriter(BsonBuffer buffer, bool disposeBuffer, BsonBinaryWriterSettings settings)
58+
: base(settings)
59+
{
4460
if (buffer == null)
4561
{
46-
_buffer = new BsonBuffer();
47-
_disposeBuffer = true; // only call Dispose if we allocated the buffer
62+
throw new ArgumentNullException("encoder");
4863
}
49-
else
64+
if (settings == null)
5065
{
51-
_buffer = buffer;
52-
_disposeBuffer = false;
66+
throw new ArgumentNullException("settings");
5367
}
68+
69+
_buffer = buffer;
70+
_disposeBuffer = disposeBuffer;
5471
_binaryWriterSettings = settings; // already frozen by base class
5572

5673
_context = null;
@@ -461,6 +478,60 @@ public override void WriteObjectId(ObjectId objectId)
461478
State = GetNextState();
462479
}
463480

481+
/// <summary>
482+
/// Writes a raw BSON array.
483+
/// </summary>
484+
/// <param name="slice">The byte buffer containing the raw BSON array.</param>
485+
/// <exception cref="System.NotImplementedException"></exception>
486+
public override void WriteRawBsonArray(IByteBuffer slice)
487+
{
488+
if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
489+
if (State != BsonWriterState.Value)
490+
{
491+
ThrowInvalidState("WriteRawBsonArray", BsonWriterState.Value);
492+
}
493+
494+
_buffer.WriteByte((byte)BsonType.Array);
495+
WriteNameHelper();
496+
_buffer.ByteBuffer.WriteBytes(slice); // assumes byteBuffer is a valid raw BSON document
497+
498+
State = GetNextState();
499+
}
500+
501+
/// <summary>
502+
/// Writes a raw BSON document.
503+
/// </summary>
504+
/// <param name="slice">The byte buffer containing the raw BSON document.</param>
505+
public override void WriteRawBsonDocument(IByteBuffer slice)
506+
{
507+
if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
508+
if (State != BsonWriterState.Initial && State != BsonWriterState.Value && State != BsonWriterState.ScopeDocument && State != BsonWriterState.Done)
509+
{
510+
ThrowInvalidState("WriteRawBsonDocument", BsonWriterState.Initial, BsonWriterState.Value, BsonWriterState.ScopeDocument, BsonWriterState.Done);
511+
}
512+
513+
if (State == BsonWriterState.Value)
514+
{
515+
_buffer.WriteByte((byte)BsonType.Document);
516+
WriteNameHelper();
517+
}
518+
_buffer.ByteBuffer.WriteBytes(slice); // assumes byteBuffer is a valid raw BSON document
519+
520+
if (_context == null)
521+
{
522+
State = BsonWriterState.Done;
523+
}
524+
else
525+
{
526+
if (_context.ContextType == ContextType.JavaScriptWithScope)
527+
{
528+
BackpatchSize(); // size of the JavaScript with scope value
529+
_context = _context.ParentContext;
530+
}
531+
State = GetNextState();
532+
}
533+
}
534+
464535
/// <summary>
465536
/// Writes a BSON regular expression to the writer.
466537
/// </summary>
@@ -612,9 +683,10 @@ protected override void Dispose(bool disposing)
612683
if (_disposeBuffer)
613684
{
614685
_buffer.Dispose();
615-
_buffer = null;
616686
}
687+
_buffer = null;
617688
}
689+
base.Dispose(disposing);
618690
}
619691

620692
// private methods

0 commit comments

Comments
 (0)