Procházet zdrojové kódy

L#方案无法支持async await语法,并且无法使用反射,缺陷太大

tanghai před 9 roky
rodič
revize
970061a2f7
100 změnil soubory, kde provedl 13332 přidání a 0 odebrání
  1. 9 0
      Unity/Assets/Plugins/MongoDB.meta
  2. 5 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson.meta
  3. 61 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonConstants.cs
  4. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonConstants.cs.meta
  5. 58 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonDefaults.cs
  6. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonDefaults.cs.meta
  7. 322 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonExtensionMethods.cs
  8. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonExtensionMethods.cs.meta
  9. 214 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonUtils.cs
  10. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonUtils.cs.meta
  11. 5 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions.meta
  12. 75 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonException.cs
  13. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonException.cs.meta
  14. 65 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonInternalException.cs
  15. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonInternalException.cs.meta
  16. 65 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonSerializationException.cs
  17. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonSerializationException.cs.meta
  18. 58 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/DuplicateBsonMemberMapAttributeException.cs
  19. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/DuplicateBsonMemberMapAttributeException.cs.meta
  20. 65 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/TruncationException.cs
  21. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/TruncationException.cs.meta
  22. 5 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO.meta
  23. 716 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReader.cs
  24. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReader.cs.meta
  25. 52 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderBookmark.cs
  26. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderBookmark.cs.meta
  27. 69 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderContext.cs
  28. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderContext.cs.meta
  29. 184 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs
  30. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs.meta
  31. 752 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriter.cs
  32. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriter.cs.meta
  33. 59 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterContext.cs
  34. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterContext.cs.meta
  35. 167 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs
  36. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs.meta
  37. 804 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBuffer.cs
  38. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBuffer.cs.meta
  39. 105 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunk.cs
  40. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunk.cs.meta
  41. 128 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunkPool.cs
  42. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunkPool.cs.meta
  43. 518 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReader.cs
  44. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReader.cs.meta
  45. 52 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderBookmark.cs
  46. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderBookmark.cs.meta
  47. 124 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderContext.cs
  48. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderContext.cs.meta
  49. 88 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs
  50. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs.meta
  51. 525 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriter.cs
  52. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriter.cs.meta
  53. 91 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterContext.cs
  54. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterContext.cs.meta
  55. 89 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterSettings.cs
  56. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterSettings.cs.meta
  57. 959 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReader.cs
  58. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReader.cs.meta
  59. 67 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderBookmark.cs
  60. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderBookmark.cs.meta
  61. 121 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderSettings.cs
  62. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderSettings.cs.meta
  63. 60 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderState.cs
  64. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderState.cs.meta
  65. 307 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonTrie.cs
  66. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonTrie.cs.meta
  67. 910 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriter.cs
  68. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriter.cs.meta
  69. 135 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterSettings.cs
  70. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterSettings.cs.meta
  71. 48 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterState.cs
  72. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterState.cs.meta
  73. 538 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteArrayBuffer.cs
  74. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteArrayBuffer.cs.meta
  75. 98 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteBufferFactory.cs
  76. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteBufferFactory.cs.meta
  77. 44 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ContextType.cs
  78. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ContextType.cs.meta
  79. 162 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/IByteBuffer.cs
  80. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/IByteBuffer.cs.meta
  81. 99 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonBuffer.cs
  82. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonBuffer.cs.meta
  83. 47 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonOutputMode.cs
  84. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonOutputMode.cs.meta
  85. 1643 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReader.cs
  86. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReader.cs.meta
  87. 76 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderBookmark.cs
  88. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderBookmark.cs.meta
  89. 57 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderContext.cs
  90. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderContext.cs.meta
  91. 108 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderSettings.cs
  92. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderSettings.cs.meta
  93. 532 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonScanner.cs
  94. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonScanner.cs.meta
  95. 496 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonToken.cs
  96. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonToken.cs.meta
  97. 855 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriter.cs
  98. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriter.cs.meta
  99. 56 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriterContext.cs
  100. 8 0
      Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriterContext.cs.meta

+ 9 - 0
Unity/Assets/Plugins/MongoDB.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 8841b3184413e144286edd6c840fa6bc
+folderAsset: yes
+timeCreated: 1463841468
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 5 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 39cbf921dcbc4bc4a93b693b5d822fff
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 61 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonConstants.cs

@@ -0,0 +1,61 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// A static class containing BSON constants.
+    /// </summary>
+    public static class BsonConstants
+    {
+        // private static fields
+        private static readonly long __dateTimeMaxValueMillisecondsSinceEpoch;
+        private static readonly long __dateTimeMinValueMillisecondsSinceEpoch;
+        private static readonly DateTime __unixEpoch;
+
+        // static constructor
+        static BsonConstants()
+        {
+            // unixEpoch has to be initialized first
+            __unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+            __dateTimeMaxValueMillisecondsSinceEpoch = (DateTime.MaxValue - __unixEpoch).Ticks / 10000;
+            __dateTimeMinValueMillisecondsSinceEpoch = (DateTime.MinValue - __unixEpoch).Ticks / 10000;
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets the number of milliseconds since the Unix epoch for DateTime.MaxValue.
+        /// </summary>
+        public static long DateTimeMaxValueMillisecondsSinceEpoch
+        {
+            get { return __dateTimeMaxValueMillisecondsSinceEpoch; }
+        }
+
+        /// <summary>
+        /// Gets the number of milliseconds since the Unix epoch for DateTime.MinValue.
+        /// </summary>
+        public static long DateTimeMinValueMillisecondsSinceEpoch
+        {
+            get { return __dateTimeMinValueMillisecondsSinceEpoch; }
+        }
+
+        /// <summary>
+        /// Gets the Unix Epoch for BSON DateTimes (1970-01-01).
+        /// </summary>
+        public static DateTime UnixEpoch { get { return __unixEpoch; } }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonConstants.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fd4be2b8d034a5747b0e38e2931f9c53
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 58 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonDefaults.cs

@@ -0,0 +1,58 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// A static helper class containing BSON defaults.
+    /// </summary>
+    public static class BsonDefaults
+    {
+        // private static fields
+        private static GuidRepresentation __guidRepresentation = GuidRepresentation.CSharpLegacy;
+        private static int __maxDocumentSize = int.MaxValue;
+        private static int __maxSerializationDepth = 100;
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default representation to be used in serialization of 
+        /// Guids to the database. 
+        /// <seealso cref="MongoDB.Bson.GuidRepresentation"/> 
+        /// </summary>
+        public static GuidRepresentation GuidRepresentation
+        {
+            get { return __guidRepresentation; }
+            set { __guidRepresentation = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the default max document size. The default is 4MiB.
+        /// </summary>
+        public static int MaxDocumentSize
+        {
+            get { return __maxDocumentSize; }
+            set { __maxDocumentSize = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the default max serialization depth (used to detect circular references during serialization). The default is 100.
+        /// </summary>
+        public static int MaxSerializationDepth
+        {
+            get { return __maxSerializationDepth; }
+            set { __maxSerializationDepth = value; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonDefaults.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5939639edb3f9534694cbd0a2af84dfc
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 322 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonExtensionMethods.cs

@@ -0,0 +1,322 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using MongoDB.Bson.IO;
+using MongoDB.Bson.Serialization;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// A static class containing BSON extension methods.
+    /// </summary>
+    public static class BsonExtensionMethods
+    {
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson<TNominalType>(this TNominalType obj)
+        {
+            return ToBson(obj, typeof(TNominalType));
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson<TNominalType>(this TNominalType obj, IBsonSerializationOptions options)
+        {
+            return ToBson(obj, typeof(TNominalType), options);
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <param name="settings">The BsonBinaryWriter settings.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson<TNominalType>(
+            this TNominalType obj,
+            IBsonSerializationOptions options,
+            BsonBinaryWriterSettings settings)
+        {
+            return ToBson(obj, typeof(TNominalType), options, settings);
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="settings">The BsonBinaryWriter settings.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson<TNominalType>(this TNominalType obj, BsonBinaryWriterSettings settings)
+        {
+            return ToBson(obj, typeof(TNominalType), settings);
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson(this object obj, Type nominalType)
+        {
+            return ToBson(obj, nominalType, BsonBinaryWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson(this object obj, Type nominalType, IBsonSerializationOptions options)
+        {
+            return ToBson(obj, nominalType, options, BsonBinaryWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <param name="settings">The BsonBinaryWriter settings.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson(
+            this object obj,
+            Type nominalType,
+            IBsonSerializationOptions options,
+            BsonBinaryWriterSettings settings)
+        {
+            using (var buffer = new BsonBuffer())
+            {
+                using (var bsonWriter = BsonWriter.Create(buffer, settings))
+                {
+                    BsonSerializer.Serialize(bsonWriter, nominalType, obj, options);
+                }
+                return buffer.ToByteArray();
+            }
+        }
+
+        /// <summary>
+        /// Converts an object to a BSON document byte array.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="settings">The BsonBinaryWriter settings.</param>
+        /// <returns>A byte array.</returns>
+        public static byte[] ToBson(this object obj, Type nominalType, BsonBinaryWriterSettings settings)
+        {
+            return ToBson(obj, nominalType, null, settings);
+        }
+
+        /// <summary>
+        /// Converts an object to a BsonDocument.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <returns>A BsonDocument.</returns>
+        public static BsonDocument ToBsonDocument<TNominalType>(this TNominalType obj)
+        {
+            return ToBsonDocument(obj, typeof(TNominalType));
+        }
+
+        /// <summary>
+        /// Converts an object to a BsonDocument.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A BsonDocument.</returns>
+        public static BsonDocument ToBsonDocument<TNominalType>(
+            this TNominalType obj,
+            IBsonSerializationOptions options)
+        {
+            return ToBsonDocument(obj, typeof(TNominalType), options);
+        }
+
+        /// <summary>
+        /// Converts an object to a BsonDocument.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <returns>A BsonDocument.</returns>
+        public static BsonDocument ToBsonDocument(this object obj, Type nominalType)
+        {
+            return ToBsonDocument(obj, nominalType, null);
+        }
+
+        /// <summary>
+        /// Converts an object to a BsonDocument.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A BsonDocument.</returns>
+        public static BsonDocument ToBsonDocument(
+            this object obj,
+            Type nominalType,
+            IBsonSerializationOptions options)
+        {
+            if (obj == null)
+            {
+                return null;
+            }
+
+            var bsonDocument = obj as BsonDocument;
+            if (bsonDocument != null)
+            {
+                return bsonDocument; // it's already a BsonDocument
+            }
+
+            var convertibleToBsonDocument = obj as IConvertibleToBsonDocument;
+            if (convertibleToBsonDocument != null)
+            {
+                return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method
+            }
+
+            // otherwise serialize into a new BsonDocument
+            var document = new BsonDocument();
+            using (var writer = BsonWriter.Create(document))
+            {
+                BsonSerializer.Serialize(writer, nominalType, obj, options);
+            }
+            return document;
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson<TNominalType>(this TNominalType obj)
+        {
+            return ToJson(obj, typeof(TNominalType));
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson<TNominalType>(this TNominalType obj, IBsonSerializationOptions options)
+        {
+            return ToJson(obj, typeof(TNominalType), options);
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <param name="settings">The JsonWriter settings.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson<TNominalType>(
+            this TNominalType obj,
+            IBsonSerializationOptions options,
+            JsonWriterSettings settings)
+        {
+            return ToJson(obj, typeof(TNominalType), options, settings);
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <typeparam name="TNominalType">The nominal type of the object.</typeparam>
+        /// <param name="obj">The object.</param>
+        /// <param name="settings">The JsonWriter settings.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson<TNominalType>(this TNominalType obj, JsonWriterSettings settings)
+        {
+            return ToJson(obj, typeof(TNominalType), settings);
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson(this object obj, Type nominalType)
+        {
+            return ToJson(obj, nominalType, JsonWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson(this object obj, Type nominalType, IBsonSerializationOptions options)
+        {
+            return ToJson(obj, nominalType, options, JsonWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="options">The serialization options.</param>
+        /// <param name="settings">The JsonWriter settings.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson(
+            this object obj,
+            Type nominalType,
+            IBsonSerializationOptions options,
+            JsonWriterSettings settings)
+        {
+            using (var stringWriter = new StringWriter())
+            {
+                using (var bsonWriter = BsonWriter.Create(stringWriter, settings))
+                {
+                    BsonSerializer.Serialize(bsonWriter, nominalType, obj, options);
+                }
+                return stringWriter.ToString();
+            }
+        }
+
+        /// <summary>
+        /// Converts an object to a JSON string.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <param name="nominalType">The nominal type of the object.</param>
+        /// <param name="settings">The JsonWriter settings.</param>
+        /// <returns>A JSON string.</returns>
+        public static string ToJson(this object obj, Type nominalType, JsonWriterSettings settings)
+        {
+            return ToJson(obj, nominalType, null, settings);
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonExtensionMethods.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 9e5d3e4779adbd44fb162e4bc24e64ef
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 214 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonUtils.cs

@@ -0,0 +1,214 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace MongoDB.Bson
+{
+
+    /// <summary>
+    /// A static class containing BSON utility methods.
+    /// </summary>
+    public static class BsonUtils
+    {
+
+        // public static methods
+        /// <summary>
+        /// Gets a friendly class name suitable for use in error messages.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <returns>A friendly class name.</returns>
+        public static string GetFriendlyTypeName(Type type)
+        {
+            if (!type.IsGenericType)
+            {
+                return type.Name;
+            }
+
+            var sb = new StringBuilder();
+            sb.AppendFormat("{0}<", Regex.Replace(type.Name, @"\`\d+$", ""));
+            foreach (var typeParameter in type.GetGenericArguments())
+            {
+                sb.AppendFormat("{0}, ", GetFriendlyTypeName(typeParameter));
+            }
+            sb.Remove(sb.Length - 2, 2);
+            sb.Append(">");
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// Parses a hex string into its equivalent byte array.
+        /// </summary>
+        /// <param name="s">The hex string to parse.</param>
+        /// <returns>The byte equivalent of the hex string.</returns>
+        public static byte[] ParseHexString(string s)
+        {
+            if (s == null)
+            {
+                throw new ArgumentNullException("s");
+            }
+
+            byte[] bytes;
+            if ((s.Length & 1) != 0) 
+            {
+                s = "0" + s; // make length of s even
+            } 
+            bytes = new byte[s.Length / 2];
+            for (int i = 0; i < bytes.Length; i++)
+            {
+                string hex = s.Substring(2 * i, 2);
+                try
+                {
+                    byte b = Convert.ToByte(hex, 16);
+                    bytes[i] = b;
+                }
+                catch (FormatException e)
+                {
+                    throw new FormatException(
+                        string.Format("Invalid hex string {0}. Problem with substring {1} starting at position {2}",
+                        s,
+                        hex,
+                        2 * i),
+                        e);
+                }
+            }
+
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts from number of milliseconds since Unix epoch to DateTime.
+        /// </summary>
+        /// <param name="millisecondsSinceEpoch">The number of milliseconds since Unix epoch.</param>
+        /// <returns>A DateTime.</returns>
+        public static DateTime ToDateTimeFromMillisecondsSinceEpoch(long millisecondsSinceEpoch)
+        {
+            if (millisecondsSinceEpoch < BsonConstants.DateTimeMinValueMillisecondsSinceEpoch ||
+                millisecondsSinceEpoch > BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
+            {
+                var message = string.Format(
+                    "The value {0} for the BsonDateTime MillisecondsSinceEpoch is outside the"+
+                    "range that can be converted to a .NET DateTime.",
+                    millisecondsSinceEpoch);
+                throw new ArgumentOutOfRangeException("millisecondsSinceEpoch", message);
+            }
+
+            // MaxValue has to be handled specially to avoid rounding errors
+            if (millisecondsSinceEpoch == BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
+            {
+                return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
+            }
+            else
+            {
+                return BsonConstants.UnixEpoch.AddTicks(millisecondsSinceEpoch * 10000);
+            }
+        }
+
+        /// <summary>
+        /// Converts a byte array to a hex string.
+        /// </summary>
+        /// <param name="bytes">The byte array.</param>
+        /// <returns>A hex string.</returns>
+        public static string ToHexString(byte[] bytes)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            var sb = new StringBuilder(bytes.Length * 2);
+            foreach (var b in bytes)
+            {
+                sb.AppendFormat("{0:x2}", b);
+            }
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// Converts a DateTime to local time (with special handling for MinValue and MaxValue).
+        /// </summary>
+        /// <param name="dateTime">A DateTime.</param>
+        /// <returns>The DateTime in local time.</returns>
+        public static DateTime ToLocalTime(DateTime dateTime)
+        {
+            if (dateTime == DateTime.MinValue)
+            {
+                return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Local);
+            }
+            else if (dateTime == DateTime.MaxValue)
+            {
+                return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Local);
+            }
+            else
+            {
+                return dateTime.ToLocalTime();
+            }
+        }
+
+        /// <summary>
+        /// Converts a DateTime to number of milliseconds since Unix epoch.
+        /// </summary>
+        /// <param name="dateTime">A DateTime.</param>
+        /// <returns>Number of seconds since Unix epoch.</returns>
+        public static long ToMillisecondsSinceEpoch(DateTime dateTime)
+        {
+            var utcDateTime = ToUniversalTime(dateTime);
+            return (utcDateTime - BsonConstants.UnixEpoch).Ticks / 10000;
+        }
+
+        /// <summary>
+        /// Converts a DateTime to UTC (with special handling for MinValue and MaxValue).
+        /// </summary>
+        /// <param name="dateTime">A DateTime.</param>
+        /// <returns>The DateTime in UTC.</returns>
+        public static DateTime ToUniversalTime(DateTime dateTime)
+        {
+            if (dateTime == DateTime.MinValue)
+            {
+                return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+            }
+            else if (dateTime == DateTime.MaxValue)
+            {
+                return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
+            }
+            else
+            {
+                return dateTime.ToUniversalTime();
+            }
+        }
+
+        /// <summary>
+        /// Tries to parse a hex string to a byte array.
+        /// </summary>
+        /// <param name="s">The hex string.</param>
+        /// <param name="bytes">A byte array.</param>
+        /// <returns>True if the hex string was successfully parsed.</returns>
+        public static bool TryParseHexString(string s, out byte[] bytes)
+        {
+            try
+            {
+                bytes = ParseHexString(s);
+            }
+            catch
+            {
+                bytes = null;
+                return false;
+            }
+
+            return true;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/BsonUtils.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 530321501c2b5504c9193c1bb8627794
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 5 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: a372566b919124f4d91bdb8e3c9c2221
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 75 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonException.cs

@@ -0,0 +1,75 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// Represents a BSON exception.
+    /// </summary>
+    [Serializable]
+    public class BsonException : Exception
+    {
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonException class.
+        /// </summary>
+        public BsonException()
+            : base()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        public BsonException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public BsonException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonException class.
+        /// </summary>
+        /// <param name="format">The error message format string.</param>
+        /// <param name="args">One or more args for the error message.</param>
+        public BsonException(string format, params object[] args)
+            : base(string.Format(format, args))
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonException class (this overload used by deserialization).
+        /// </summary>
+        /// <param name="info">The SerializationInfo.</param>
+        /// <param name="context">The StreamingContext.</param>
+        public BsonException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonException.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7c4e01c6066b7be4b87a0b683389dd5c
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 65 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonInternalException.cs

@@ -0,0 +1,65 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// Represents a BSON internal exception (almost surely the result of a bug).
+    /// </summary>
+    [Serializable]
+    public class BsonInternalException : BsonException
+    {
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonInternalException class.
+        /// </summary>
+        public BsonInternalException()
+            : base()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonInternalException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        public BsonInternalException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonInternalException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public BsonInternalException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonInternalException class (this overload used by deserialization).
+        /// </summary>
+        /// <param name="info">The SerializationInfo.</param>
+        /// <param name="context">The StreamingContext.</param>
+        public BsonInternalException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonInternalException.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c03f560ff6e57574c8cbbbe73346a0b9
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 65 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonSerializationException.cs

@@ -0,0 +1,65 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// Represents a BSON serialization exception.
+    /// </summary>
+    [Serializable]
+    public class BsonSerializationException : BsonException
+    {
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonSerializationException class.
+        /// </summary>
+        public BsonSerializationException()
+            : base()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonSerializationException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        public BsonSerializationException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonSerializationException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public BsonSerializationException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonSerializationException class (this overload used by deserialization).
+        /// </summary>
+        /// <param name="info">The SerializationInfo.</param>
+        /// <param name="context">The StreamingContext.</param>
+        public BsonSerializationException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/BsonSerializationException.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7ef7520c011708245850c5e7bd79d0f7
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 58 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/DuplicateBsonMemberMapAttributeException.cs

@@ -0,0 +1,58 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// Indicates that an attribute restricted to one member has been applied to multiple members.
+    /// </summary>
+    [Serializable]
+    public class DuplicateBsonMemberMapAttributeException : BsonException
+    {
+        // constructors 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DuplicateBsonMemberMapAttributeException" /> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public DuplicateBsonMemberMapAttributeException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DuplicateBsonMemberMapAttributeException" /> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="inner">The inner.</param>
+        public DuplicateBsonMemberMapAttributeException(string message, Exception inner)
+            : base(message, inner)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DuplicateBsonMemberMapAttributeException" /> class.
+        /// </summary>
+        /// <param name="info">The info.</param>
+        /// <param name="context">The context.</param>
+        protected DuplicateBsonMemberMapAttributeException(
+          System.Runtime.Serialization.SerializationInfo info,
+          System.Runtime.Serialization.StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/DuplicateBsonMemberMapAttributeException.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3f6b60d31c63c924ab75234b4e23421f
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 65 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/TruncationException.cs

@@ -0,0 +1,65 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace MongoDB.Bson
+{
+    /// <summary>
+    /// Represents a truncation exception.
+    /// </summary>
+    [Serializable]
+    public class TruncationException : BsonException
+    {
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the TruncationException class.
+        /// </summary>
+        public TruncationException()
+            : this("Truncation resulted in data loss.")
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the TruncationException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        public TruncationException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the TruncationException class.
+        /// </summary>
+        /// <param name="message">The error message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public TruncationException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the TruncationException class (this overload used by deserialization).
+        /// </summary>
+        /// <param name="info">The SerializationInfo.</param>
+        /// <param name="context">The StreamingContext.</param>
+        public TruncationException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/Exceptions/TruncationException.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 22e7ec2e14fb871438082dcfa7b9b32b
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 5 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 22d7dc519ad0d8d4fa3b81817f18edc5
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 716 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReader.cs

@@ -0,0 +1,716 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON reader for a binary BSON byte array.
+    /// </summary>
+    public class BsonBinaryReader : BsonReader
+    {
+        // private fields
+        private BsonBuffer _buffer; // if reading from a stream Create will have loaded the buffer
+        private bool _disposeBuffer;
+        private BsonBinaryReaderSettings _binaryReaderSettings; // same value as in base class just declared as derived class
+        private BsonBinaryReaderContext _context;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryReader class.
+        /// </summary>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <param name="settings">A BsonBinaryReaderSettings.</param>
+        public BsonBinaryReader(BsonBuffer buffer, BsonBinaryReaderSettings settings)
+            : this(buffer ?? new BsonBuffer(), buffer == null, settings)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryReader class.
+        /// </summary>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <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>
+        /// <param name="settings">A BsonBinaryReaderSettings.</param>
+        /// <exception cref="System.ArgumentNullException">
+        /// buffer
+        /// or
+        /// settings
+        /// </exception>
+        public BsonBinaryReader(BsonBuffer buffer, bool disposeBuffer, BsonBinaryReaderSettings settings)
+            : base(settings)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+
+            _buffer = buffer;
+            _disposeBuffer = disposeBuffer;
+            _binaryReaderSettings = settings; // already frozen by base class
+
+            _context = new BsonBinaryReaderContext(null, ContextType.TopLevel, 0, 0);
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the reader's buffer.
+        /// </summary>
+        public BsonBuffer Buffer
+        {
+            get { return _buffer; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the reader.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonReaderState.Closed)
+            {
+                State = BsonReaderState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Gets a bookmark to the reader's current position and state.
+        /// </summary>
+        /// <returns>A bookmark.</returns>
+        public override BsonReaderBookmark GetBookmark()
+        {
+            return new BsonBinaryReaderBookmark(State, CurrentBsonType, CurrentName, _context, _buffer.Position);
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A BsonBinaryData.</returns>
+#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
+        public override BsonBinaryData ReadBinaryData()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBinaryData", BsonType.Binary);
+
+            int size = ReadSize();
+
+            var subType = (BsonBinarySubType)_buffer.ReadByte();
+            if (subType == BsonBinarySubType.OldBinary)
+            {
+                // sub type OldBinary has two sizes (for historical reasons)
+                int size2 = ReadSize();
+                if (size2 != size - 4)
+                {
+                    throw new Exception("Binary sub type OldBinary has inconsistent sizes");
+                }
+                size = size2;
+
+                if (_binaryReaderSettings.FixOldBinarySubTypeOnInput)
+                {
+                    subType = BsonBinarySubType.Binary; // replace obsolete OldBinary with new Binary sub type
+                }
+            }
+
+            var bytes = _buffer.ReadBytes(size);
+
+            var guidRepresentation = GuidRepresentation.Unspecified;
+            if (subType == BsonBinarySubType.UuidLegacy || subType == BsonBinarySubType.UuidStandard)
+            {
+                if (_binaryReaderSettings.GuidRepresentation != GuidRepresentation.Unspecified)
+                {
+                    var expectedSubType = (_binaryReaderSettings.GuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
+                    if (subType != expectedSubType)
+                    {
+                        var message = string.Format(
+                            "The GuidRepresentation for the reader is {0}, which requires the binary sub type to be {1}, not {2}.",
+                            _binaryReaderSettings.GuidRepresentation, expectedSubType, subType);
+                        throw new Exception(message);
+                    }
+                }
+                guidRepresentation = (subType == BsonBinarySubType.UuidStandard) ? GuidRepresentation.Standard : _binaryReaderSettings.GuidRepresentation;
+            }
+
+            State = GetNextState();
+            return new BsonBinaryData(bytes, subType, guidRepresentation);
+        }
+#pragma warning restore 618
+
+        /// <summary>
+        /// Reads a BSON boolean from the reader.
+        /// </summary>
+        /// <returns>A Boolean.</returns>
+        public override bool ReadBoolean()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBoolean", BsonType.Boolean);
+            State = GetNextState();
+            return _buffer.ReadBoolean();
+        }
+
+        /// <summary>
+        /// Reads a BsonType from the reader.
+        /// </summary>
+        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+        /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
+        /// <param name="found">Set to true if a matching value was found in the trie.</param>
+        /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
+        /// <returns>A BsonType.</returns>
+        public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            found = false;
+            value = default(TValue);
+            if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument)
+            {
+                // there is an implied type of Document for the top level and for scope documents
+                CurrentBsonType = BsonType.Document;
+                State = BsonReaderState.Value;
+                return CurrentBsonType;
+            }
+            if (State != BsonReaderState.Type)
+            {
+                ThrowInvalidState("ReadBsonType", BsonReaderState.Type);
+            }
+
+            CurrentBsonType = _buffer.ReadBsonType();
+
+            if (CurrentBsonType == BsonType.EndOfDocument)
+            {
+                switch (_context.ContextType)
+                {
+                    case ContextType.Array:
+                        State = BsonReaderState.EndOfArray;
+                        return BsonType.EndOfDocument;
+                    case ContextType.Document:
+                    case ContextType.ScopeDocument:
+                        State = BsonReaderState.EndOfDocument;
+                        return BsonType.EndOfDocument;
+                    default:
+                        var message = string.Format("BsonType EndOfDocument is not valid when ContextType is {0}.", _context.ContextType);
+                        throw new Exception(message);
+                }
+            }
+            else
+            {
+                switch (_context.ContextType)
+                {
+                    case ContextType.Array:
+                        _buffer.SkipCString(); // ignore array element names
+                        State = BsonReaderState.Value;
+                        break;
+                    case ContextType.Document:
+                    case ContextType.ScopeDocument:
+                        CurrentName = _buffer.ReadName(bsonTrie, out found, out value);
+                        State = BsonReaderState.Name;
+                        break;
+                    default:
+                        throw new BsonInternalException("Unexpected ContextType.");
+                }
+
+                return CurrentBsonType;
+            }
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A byte array.</returns>
+#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
+        public override byte[] ReadBytes()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBytes", BsonType.Binary);
+
+            int size = ReadSize();
+
+            var subType = (BsonBinarySubType)_buffer.ReadByte();
+            if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
+            {
+                var message = string.Format("ReadBytes requires the binary sub type to be Binary, not {2}.", subType);
+                throw new Exception(message);
+            }
+
+            State = GetNextState();
+            return _buffer.ReadBytes(size);
+        }
+#pragma warning restore 618
+
+        /// <summary>
+        /// Reads a BSON DateTime from the reader.
+        /// </summary>
+        /// <returns>The number of milliseconds since the Unix epoch.</returns>
+        public override long ReadDateTime()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDateTime", BsonType.DateTime);
+            State = GetNextState();
+            var value = _buffer.ReadInt64();
+            if (value == BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch + 1)
+            {
+                if (_binaryReaderSettings.FixOldDateTimeMaxValueOnInput)
+                {
+                    value = BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch;
+                }
+            }
+            return value;
+        }
+
+        /// <summary>
+        /// Reads a BSON Double from the reader.
+        /// </summary>
+        /// <returns>A Double.</returns>
+        public override double ReadDouble()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDouble", BsonType.Double);
+            State = GetNextState();
+            return _buffer.ReadDouble();
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON array from the reader.
+        /// </summary>
+        public override void ReadEndArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Array)
+            {
+                ThrowInvalidContextType("ReadEndArray", _context.ContextType, ContextType.Array);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfArray if at end of array
+            }
+            if (State != BsonReaderState.EndOfArray)
+            {
+                ThrowInvalidState("ReadEndArray", BsonReaderState.EndOfArray);
+            }
+
+            _context = _context.PopContext(_buffer.Position);
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON document from the reader.
+        /// </summary>
+        public override void ReadEndDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
+            {
+                ThrowInvalidContextType("ReadEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfDocument if at end of document
+            }
+            if (State != BsonReaderState.EndOfDocument)
+            {
+                ThrowInvalidState("ReadEndDocument", BsonReaderState.EndOfDocument);
+            }
+
+            _context = _context.PopContext(_buffer.Position);
+            if (_context.ContextType == ContextType.JavaScriptWithScope)
+            {
+                _context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
+            }
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON Int32 from the reader.
+        /// </summary>
+        /// <returns>An Int32.</returns>
+        public override int ReadInt32()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt32", BsonType.Int32);
+            State = GetNextState();
+            return _buffer.ReadInt32();
+        }
+
+        /// <summary>
+        /// Reads a BSON Int64 from the reader.
+        /// </summary>
+        /// <returns>An Int64.</returns>
+        public override long ReadInt64()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt64", BsonType.Int64);
+            State = GetNextState();
+            return _buffer.ReadInt64();
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScript()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScript", BsonType.JavaScript);
+            State = GetNextState();
+            return _buffer.ReadString(_binaryReaderSettings.Encoding);
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScriptWithScope()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScriptWithScope", BsonType.JavaScriptWithScope);
+
+            var startPosition = _buffer.Position; // position of size field
+            var size = ReadSize();
+            _context = new BsonBinaryReaderContext(_context, ContextType.JavaScriptWithScope, startPosition, size);
+            var code = _buffer.ReadString(_binaryReaderSettings.Encoding);
+
+            State = BsonReaderState.ScopeDocument;
+            return code;
+        }
+
+        /// <summary>
+        /// Reads a BSON MaxKey from the reader.
+        /// </summary>
+        public override void ReadMaxKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMaxKey", BsonType.MaxKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON MinKey from the reader.
+        /// </summary>
+        public override void ReadMinKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMinKey", BsonType.MinKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON null from the reader.
+        /// </summary>
+        public override void ReadNull()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadNull", BsonType.Null);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <returns>An ObjectId.</returns>
+        public override ObjectId ReadObjectId()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadObjectId", BsonType.ObjectId);
+            State = GetNextState();
+            return _buffer.ReadObjectId();
+        }
+
+        /// <summary>
+        /// Reads a raw BSON array.
+        /// </summary>
+        /// <returns>
+        /// The raw BSON array.
+        /// </returns>
+        public override IByteBuffer ReadRawBsonArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadRawBsonArray", BsonType.Array);
+
+            var position = _buffer.Position;
+            var length = _buffer.ReadInt32();
+            var slice = _buffer.ByteBuffer.GetSlice(position, length);
+            _buffer.Position = position + length;
+
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+
+            return slice;
+        }
+
+        /// <summary>
+        /// Reads a raw BSON document.
+        /// </summary>
+        /// <returns>
+        /// The raw BSON document.
+        /// </returns>
+        public override IByteBuffer ReadRawBsonDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadRawBsonDocument", BsonType.Document);
+
+            var position = _buffer.Position;
+            var length = _buffer.ReadInt32();
+            var slice = _buffer.ByteBuffer.GetSlice(position, length);
+            _buffer.Position = position + length;
+
+            if (_context.ContextType == ContextType.JavaScriptWithScope)
+            {
+                _context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
+            }
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+
+            return slice;
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression from the reader.
+        /// </summary>
+        /// <returns>A BsonRegularExpression.</returns>
+        public override BsonRegularExpression ReadRegularExpression()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadRegularExpression", BsonType.RegularExpression);
+            State = GetNextState();
+            var pattern = _buffer.ReadCString(_binaryReaderSettings.Encoding);
+            var options = _buffer.ReadCString(_binaryReaderSettings.Encoding);
+            return new BsonRegularExpression(pattern, options);
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON array.
+        /// </summary>
+        public override void ReadStartArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartArray", BsonType.Array);
+
+            var startPosition = _buffer.Position; // position of size field
+            var size = ReadSize();
+            _context = new BsonBinaryReaderContext(_context, ContextType.Array, startPosition, size);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON document.
+        /// </summary>
+        public override void ReadStartDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartDocument", BsonType.Document);
+
+            var contextType = (State == BsonReaderState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document;
+            var startPosition = _buffer.Position; // position of size field
+            var size = ReadSize();
+            _context = new BsonBinaryReaderContext(_context, contextType, startPosition, size);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads a BSON string from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        public override string ReadString()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadString", BsonType.String);
+            State = GetNextState();
+            return _buffer.ReadString(_binaryReaderSettings.Encoding);
+        }
+
+        /// <summary>
+        /// Reads a BSON symbol from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadSymbol()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadSymbol", BsonType.Symbol);
+            State = GetNextState();
+            return _buffer.ReadString(_binaryReaderSettings.Encoding);
+        }
+
+        /// <summary>
+        /// Reads a BSON timestamp from the reader.
+        /// </summary>
+        /// <returns>The combined timestamp/increment.</returns>
+        public override long ReadTimestamp()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadTimestamp", BsonType.Timestamp);
+            State = GetNextState();
+            return _buffer.ReadInt64();
+        }
+
+        /// <summary>
+        /// Reads a BSON undefined from the reader.
+        /// </summary>
+        public override void ReadUndefined()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadUndefined", BsonType.Undefined);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Returns the reader to previously bookmarked position and state.
+        /// </summary>
+        /// <param name="bookmark">The bookmark.</param>
+        public override void ReturnToBookmark(BsonReaderBookmark bookmark)
+        {
+            var binaryReaderBookmark = (BsonBinaryReaderBookmark)bookmark;
+            State = binaryReaderBookmark.State;
+            CurrentBsonType = binaryReaderBookmark.CurrentBsonType;
+            CurrentName = binaryReaderBookmark.CurrentName;
+            _context = binaryReaderBookmark.CloneContext();
+            _buffer.Position = binaryReaderBookmark.Position;
+        }
+
+        /// <summary>
+        /// Skips the name (reader must be positioned on a name).
+        /// </summary>
+        public override void SkipName()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Name)
+            {
+                ThrowInvalidState("SkipName", BsonReaderState.Name);
+            }
+
+            State = BsonReaderState.Value;
+        }
+
+        /// <summary>
+        /// Skips the value (reader must be positioned on a value).
+        /// </summary>
+        public override void SkipValue()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Value)
+            {
+                ThrowInvalidState("SkipValue", BsonReaderState.Value);
+            }
+
+            int skip;
+            switch (CurrentBsonType)
+            {
+                case BsonType.Array: skip = ReadSize() - 4; break;
+                case BsonType.Binary: skip = ReadSize() + 1; break;
+                case BsonType.Boolean: skip = 1; break;
+                case BsonType.DateTime: skip = 8; break;
+                case BsonType.Document: skip = ReadSize() - 4; break;
+                case BsonType.Double: skip = 8; break;
+                case BsonType.Int32: skip = 4; break;
+                case BsonType.Int64: skip = 8; break;
+                case BsonType.JavaScript: skip = ReadSize(); break;
+                case BsonType.JavaScriptWithScope: skip = ReadSize() - 4; break;
+                case BsonType.MaxKey: skip = 0; break;
+                case BsonType.MinKey: skip = 0; break;
+                case BsonType.Null: skip = 0; break;
+                case BsonType.ObjectId: skip = 12; break;
+                case BsonType.RegularExpression: _buffer.SkipCString(); _buffer.SkipCString(); skip = 0; break;
+                case BsonType.String: skip = ReadSize(); break;
+                case BsonType.Symbol: skip = ReadSize(); break;
+                case BsonType.Timestamp: skip = 8; break;
+                case BsonType.Undefined: skip = 0; break;
+                default: throw new BsonInternalException("Unexpected BsonType.");
+            }
+            _buffer.Skip(skip);
+
+            State = BsonReaderState.Type;
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the reader.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                try
+                {
+                    Close();
+                    if (_buffer != null)
+                    {
+                        if (_disposeBuffer)
+                        {
+                            _buffer.Dispose();
+                        }
+                        _buffer = null;
+                    }
+                }
+                catch { } // ignore exceptions
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private BsonReaderState GetNextState()
+        {
+            switch (_context.ContextType)
+            {
+                case ContextType.Array:
+                case ContextType.Document:
+                case ContextType.ScopeDocument:
+                    return BsonReaderState.Type;
+                case ContextType.TopLevel:
+                    return BsonReaderState.Done;
+                default:
+                    throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        private int ReadSize()
+        {
+            int size = _buffer.ReadInt32();
+            if (size < 0)
+            {
+                var message = string.Format("Size {0} is not valid because it is negative.", size);
+                throw new Exception(message);
+            }
+            if (size > _binaryReaderSettings.MaxDocumentSize)
+            {
+                var message = string.Format("Size {0} is not valid because it is larger than MaxDocumentSize {1}.", size, _binaryReaderSettings.MaxDocumentSize);
+                throw new Exception(message);
+            }
+            return size;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReader.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a80ff80615d759e49aac45acd751a312
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 52 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderBookmark.cs

@@ -0,0 +1,52 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a bookmark that can be used to return a reader to the current position and state.
+    /// </summary>
+    public class BsonBinaryReaderBookmark : BsonReaderBookmark
+    {
+        // private fields
+        private BsonBinaryReaderContext _context;
+        private int _position;
+
+        // constructors
+        internal BsonBinaryReaderBookmark(
+            BsonReaderState state,
+            BsonType currentBsonType,
+            string currentName,
+            BsonBinaryReaderContext context,
+            int position)
+            : base(state, currentBsonType, currentName)
+        {
+            _context = context.Clone();
+            _position = position;
+        }
+
+        // internal properties
+        internal int Position
+        {
+            get { return _position; }
+        }
+
+        // internal methods
+        internal BsonBinaryReaderContext CloneContext()
+        {
+            return _context.Clone();
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderBookmark.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4380bba3214c8a94c8fae471f9abfd7a
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 69 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderContext.cs

@@ -0,0 +1,69 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    internal class BsonBinaryReaderContext
+    {
+        // private fields
+        private BsonBinaryReaderContext _parentContext;
+        private ContextType _contextType;
+        private int _startPosition;
+        private int _size;
+
+        // constructors
+        internal BsonBinaryReaderContext(
+            BsonBinaryReaderContext parentContext,
+            ContextType contextType,
+            int startPosition, 
+            int size)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _startPosition = startPosition;
+            _size = size;
+        }
+
+        // internal properties
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the context.
+        /// </summary>
+        /// <returns>A clone of the context.</returns>
+        public BsonBinaryReaderContext Clone()
+        {
+            return new BsonBinaryReaderContext(_parentContext, _contextType, _startPosition, _size);
+        }
+
+        public BsonBinaryReaderContext PopContext(int position)
+        {
+            int actualSize = position - _startPosition;
+            if (actualSize != _size)
+            {
+                var message = string.Format("Expected size to be {0}, not {1}.", _size, actualSize);
+                throw new Exception(message);
+            }
+            return _parentContext;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bf041ffe9fe989841a3cd574309b991d
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 184 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs

@@ -0,0 +1,184 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Text;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonBinaryReader.
+    /// </summary>
+    [Serializable]
+    public class BsonBinaryReaderSettings : BsonReaderSettings
+    {
+        // private static fields
+        private static BsonBinaryReaderSettings __defaults = null; // delay creation to pick up the latest default values
+
+        // private fields
+        private bool _closeInput = false;
+        private UTF8Encoding _encoding = new UTF8Encoding(false, true);
+        private bool _fixOldBinarySubTypeOnInput = true;
+        private bool _fixOldDateTimeMaxValueOnInput = true;
+        private int _maxDocumentSize = BsonDefaults.MaxDocumentSize;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryReaderSettings class.
+        /// </summary>
+        public BsonBinaryReaderSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryReaderSettings class.
+        /// </summary>
+        /// <param name="closeInput">Whether to close the input stream when the reader is closed.</param>
+        /// <param name="fixOldBinarySubTypeOnInput">Whether to fix occurrences of the old binary subtype on input.</param>
+        /// <param name="fixOldDateTimeMaxValueOnInput">Whether to fix occurrences of the old representation of DateTime.MaxValue on input.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        /// <param name="maxDocumentSize">The max document size.</param>
+        [Obsolete("Use the no-argument constructor instead and set the properties.")]
+        public BsonBinaryReaderSettings(
+            bool closeInput,
+            bool fixOldBinarySubTypeOnInput,
+            bool fixOldDateTimeMaxValueOnInput,
+            GuidRepresentation guidRepresentation,
+            int maxDocumentSize)
+            : base(guidRepresentation)
+        {
+            _closeInput = closeInput;
+            _fixOldBinarySubTypeOnInput = fixOldBinarySubTypeOnInput;
+            _fixOldDateTimeMaxValueOnInput = fixOldDateTimeMaxValueOnInput;
+            _maxDocumentSize = maxDocumentSize;
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default settings for a BsonBinaryReader.
+        /// </summary>
+        public static BsonBinaryReaderSettings Defaults
+        {
+            get
+            {
+                if (__defaults == null)
+                {
+                    __defaults = new BsonBinaryReaderSettings();
+                }
+                return __defaults;
+            }
+            set { __defaults = value; }
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets whether to close the input stream when the reader is closed.
+        /// </summary>
+        public bool CloseInput
+        {
+            get { return _closeInput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryReaderSettings is frozen."); }
+                _closeInput = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the Encoding.
+        /// </summary>
+        public UTF8Encoding Encoding
+        {
+            get { return _encoding; }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryReaderSettings is frozen."); }
+                _encoding = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to fix occurrences of the old binary subtype on input. 
+        /// </summary>
+        public bool FixOldBinarySubTypeOnInput
+        {
+            get { return _fixOldBinarySubTypeOnInput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryReaderSettings is frozen."); }
+                _fixOldBinarySubTypeOnInput = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to fix occurrences of the old representation of DateTime.MaxValue on input. 
+        /// </summary>
+        public bool FixOldDateTimeMaxValueOnInput
+        {
+            get { return _fixOldDateTimeMaxValueOnInput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryReaderSettings is frozen."); }
+                _fixOldDateTimeMaxValueOnInput = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the max document size.
+        /// </summary>
+        public int MaxDocumentSize
+        {
+            get { return _maxDocumentSize; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryReaderSettings is frozen."); }
+                _maxDocumentSize = value;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public new BsonBinaryReaderSettings Clone()
+        {
+            return (BsonBinaryReaderSettings)CloneImplementation();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected override BsonReaderSettings CloneImplementation()
+        {
+            var clone = new BsonBinaryReaderSettings
+            {
+                CloseInput = _closeInput,
+                Encoding = _encoding,
+                FixOldBinarySubTypeOnInput = _fixOldBinarySubTypeOnInput,
+                FixOldDateTimeMaxValueOnInput = _fixOldDateTimeMaxValueOnInput,
+                GuidRepresentation = GuidRepresentation,
+                MaxDocumentSize = _maxDocumentSize
+            };
+            return clone;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0c4a0a11e2696554080efde23051bed1
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 752 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriter.cs

@@ -0,0 +1,752 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON writer to a BSON Stream.
+    /// </summary>
+    public class BsonBinaryWriter : BsonWriter
+    {
+        // private static fields
+        private static readonly UTF8Encoding __strictUtf8Encoding = new UTF8Encoding(false, true);
+
+        // private fields
+        private Stream _stream; // can be null if we're only writing to the buffer
+        private BsonBuffer _buffer;
+        private bool _disposeBuffer;
+        private BsonBinaryWriterSettings _binaryWriterSettings; // same value as in base class just declared as derived class
+        private Stack<int> _maxDocumentSizeStack = new Stack<int>();
+        private BsonBinaryWriterContext _context;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryWriter class.
+        /// </summary>
+        /// <param name="stream">A stream.</param>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <param name="settings">Optional BsonBinaryWriter settings.</param>
+        public BsonBinaryWriter(Stream stream, BsonBuffer buffer, BsonBinaryWriterSettings settings)
+            : this(buffer ?? new BsonBuffer(), buffer == null, settings)
+        {
+            _stream = stream;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryWriter class.
+        /// </summary>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <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>
+        /// <param name="settings">Optional BsonBinaryWriter settings.</param>
+        /// <exception cref="System.ArgumentNullException">
+        /// encoder
+        /// or
+        /// settings
+        /// </exception>
+        public BsonBinaryWriter(BsonBuffer buffer, bool disposeBuffer, BsonBinaryWriterSettings settings)
+            : base(settings)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("encoder");
+            }
+
+            _buffer = buffer;
+            _disposeBuffer = disposeBuffer;
+            _binaryWriterSettings = settings; // already frozen by base class
+            _maxDocumentSizeStack.Push(_binaryWriterSettings.MaxDocumentSize);
+
+            _context = null;
+            State = BsonWriterState.Initial;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the writer's BsonBuffer.
+        /// </summary>
+        public BsonBuffer Buffer
+        {
+            get { return _buffer; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the writer.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonWriterState.Closed)
+            {
+                if (State == BsonWriterState.Done)
+                {
+                    Flush();
+                }
+                if (_stream != null && _binaryWriterSettings.CloseOutput)
+                {
+                    _stream.Close();
+                }
+                _context = null;
+                State = BsonWriterState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Flushes any pending data to the output destination.
+        /// </summary>
+        public override void Flush()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State == BsonWriterState.Closed)
+            {
+                throw new InvalidOperationException("Flush called on closed BsonWriter.");
+            }
+            if (State != BsonWriterState.Done)
+            {
+                throw new InvalidOperationException("Flush called before BsonBinaryWriter was finished writing to buffer.");
+            }
+            if (_stream != null)
+            {
+                _buffer.WriteTo(_stream);
+                _stream.Flush();
+                _buffer.Clear(); // only clear the buffer if we have written it to a stream
+            }
+        }
+
+        /// <summary>
+        /// Pops the max document size stack, restoring the previous max document size.
+        /// </summary>
+        public void PopMaxDocumentSize()
+        {
+            _maxDocumentSizeStack.Pop();
+        }
+
+        /// <summary>
+        /// Pushes a new max document size onto the max document size stack.
+        /// </summary>
+        /// <param name="maxDocumentSize">The maximum size of the document.</param>
+        public void PushMaxDocumentSize(int maxDocumentSize)
+        {
+            _maxDocumentSizeStack.Push(Math.Min(maxDocumentSize, _maxDocumentSizeStack.Peek()));
+        }
+
+#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        public override void WriteBinaryData(BsonBinaryData binaryData)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBinaryData", BsonWriterState.Value);
+            }
+
+            var bytes = binaryData.Bytes;
+            var subType = binaryData.SubType;
+            var guidRepresentation = binaryData.GuidRepresentation;
+            switch (subType)
+            {
+                case BsonBinarySubType.OldBinary:
+                    if (_binaryWriterSettings.FixOldBinarySubTypeOnOutput)
+                    {
+                        subType = BsonBinarySubType.Binary; // replace obsolete OldBinary with new Binary sub type
+                    }
+                    break;
+                case BsonBinarySubType.UuidLegacy:
+                case BsonBinarySubType.UuidStandard:
+                    if (_binaryWriterSettings.GuidRepresentation != GuidRepresentation.Unspecified)
+                    {
+                        var expectedSubType = (_binaryWriterSettings.GuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
+                        if (subType != expectedSubType)
+                        {
+                            var message = string.Format(
+                                "The GuidRepresentation for the writer is {0}, which requires the subType argument to be {1}, not {2}.",
+                                _binaryWriterSettings.GuidRepresentation, expectedSubType, subType);
+                            throw new BsonSerializationException(message);
+                        }
+                        if (guidRepresentation != _binaryWriterSettings.GuidRepresentation)
+                        {
+                            var message = string.Format(
+                                "The GuidRepresentation for the writer is {0}, which requires the the guidRepresentation argument to also be {0}, not {1}.",
+                                _binaryWriterSettings.GuidRepresentation, guidRepresentation);
+                            throw new BsonSerializationException(message);
+                        }
+                    }
+                    break;
+            }
+
+            _buffer.WriteByte((byte)BsonType.Binary);
+            WriteNameHelper();
+            if (subType == BsonBinarySubType.OldBinary)
+            {
+                // sub type OldBinary has two sizes (for historical reasons)
+                _buffer.WriteInt32(bytes.Length + 4);
+                _buffer.WriteByte((byte)subType);
+                _buffer.WriteInt32(bytes.Length);
+            }
+            else
+            {
+                _buffer.WriteInt32(bytes.Length);
+                _buffer.WriteByte((byte)subType);
+            }
+            _buffer.WriteBytes(bytes);
+
+            State = GetNextState();
+        }
+#pragma warning restore 618
+
+        /// <summary>
+        /// Writes a BSON Boolean to the writer.
+        /// </summary>
+        /// <param name="value">The Boolean value.</param>
+        public override void WriteBoolean(bool value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBoolean", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Boolean);
+            WriteNameHelper();
+            _buffer.WriteBoolean(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        public override void WriteBytes(byte[] bytes)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBytes", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Binary);
+            WriteNameHelper();
+            _buffer.WriteInt32(bytes.Length);
+            _buffer.WriteByte((byte)BsonBinarySubType.Binary);
+            _buffer.WriteBytes(bytes);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON DateTime to the writer.
+        /// </summary>
+        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
+        public override void WriteDateTime(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteDateTime", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.DateTime);
+            WriteNameHelper();
+            _buffer.WriteInt64(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Double to the writer.
+        /// </summary>
+        /// <param name="value">The Double value.</param>
+        public override void WriteDouble(double value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteDouble", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Double);
+            WriteNameHelper();
+            _buffer.WriteDouble(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON array to the writer.
+        /// </summary>
+        public override void WriteEndArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteEndArray", BsonWriterState.Value);
+            }
+            if (_context.ContextType != ContextType.Array)
+            {
+                ThrowInvalidContextType("WriteEndArray", _context.ContextType, ContextType.Array);
+            }
+
+            base.WriteEndArray();
+            _buffer.WriteByte(0);
+            BackpatchSize(); // size of document
+
+            _context = _context.ParentContext;
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON document to the writer.
+        /// </summary>
+        public override void WriteEndDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Name)
+            {
+                ThrowInvalidState("WriteEndDocument", BsonWriterState.Name);
+            }
+            if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
+            {
+                ThrowInvalidContextType("WriteEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
+            }
+
+            base.WriteEndDocument();
+            _buffer.WriteByte(0);
+            BackpatchSize(); // size of document
+
+            _context = _context.ParentContext;
+            if (_context == null)
+            {
+                State = BsonWriterState.Done;
+            }
+            else
+            {
+                if (_context.ContextType == ContextType.JavaScriptWithScope)
+                {
+                    BackpatchSize(); // size of the JavaScript with scope value
+                    _context = _context.ParentContext;
+                }
+                State = GetNextState();
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON Int32 to the writer.
+        /// </summary>
+        /// <param name="value">The Int32 value.</param>
+        public override void WriteInt32(int value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteInt32", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Int32);
+            WriteNameHelper();
+            _buffer.WriteInt32(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Int64 to the writer.
+        /// </summary>
+        /// <param name="value">The Int64 value.</param>
+        public override void WriteInt64(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteInt64", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Int64);
+            WriteNameHelper();
+            _buffer.WriteInt64(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer.
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScript(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteJavaScript", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.JavaScript);
+            WriteNameHelper();
+            _buffer.WriteString(_binaryWriterSettings.Encoding, code);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer (call WriteStartDocument to start writing the scope).
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScriptWithScope(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteJavaScriptWithScope", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.JavaScriptWithScope);
+            WriteNameHelper();
+            _context = new BsonBinaryWriterContext(_context, ContextType.JavaScriptWithScope, _buffer.Position);
+            _buffer.WriteInt32(0); // reserve space for size of JavaScript with scope value
+            _buffer.WriteString(_binaryWriterSettings.Encoding, code);
+
+            State = BsonWriterState.ScopeDocument;
+        }
+
+        /// <summary>
+        /// Writes a BSON MaxKey to the writer.
+        /// </summary>
+        public override void WriteMaxKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteMaxKey", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.MaxKey);
+            WriteNameHelper();
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON MinKey to the writer.
+        /// </summary>
+        public override void WriteMinKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteMinKey", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.MinKey);
+            WriteNameHelper();
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON null to the writer.
+        /// </summary>
+        public override void WriteNull()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteNull", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Null);
+            WriteNameHelper();
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the writer.
+        /// </summary>
+        /// <param name="objectId">The ObjectId.</param>
+        public override void WriteObjectId(ObjectId objectId)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteObjectId", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.ObjectId);
+            WriteNameHelper();
+            _buffer.WriteObjectId(objectId);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a raw BSON array.
+        /// </summary>
+        /// <param name="slice">The byte buffer containing the raw BSON array.</param>
+        public override void WriteRawBsonArray(IByteBuffer slice)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteRawBsonArray", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Array);
+            WriteNameHelper();
+            _buffer.ByteBuffer.WriteBytes(slice); // assumes byteBuffer is a valid raw BSON array
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a raw BSON document.
+        /// </summary>
+        /// <param name="slice">The byte buffer containing the raw BSON document.</param>
+        public override void WriteRawBsonDocument(IByteBuffer slice)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Initial && State != BsonWriterState.Value && State != BsonWriterState.ScopeDocument && State != BsonWriterState.Done)
+            {
+                ThrowInvalidState("WriteRawBsonDocument", BsonWriterState.Initial, BsonWriterState.Value, BsonWriterState.ScopeDocument, BsonWriterState.Done);
+            }
+
+            if (State == BsonWriterState.Value)
+            {
+                _buffer.WriteByte((byte)BsonType.Document);
+                WriteNameHelper();
+            }
+            _buffer.ByteBuffer.WriteBytes(slice); // assumes byteBuffer is a valid raw BSON document
+
+            if (_context == null)
+            {
+                State = BsonWriterState.Done;
+            }
+            else
+            {
+                if (_context.ContextType == ContextType.JavaScriptWithScope)
+                {
+                    BackpatchSize(); // size of the JavaScript with scope value
+                    _context = _context.ParentContext;
+                }
+                State = GetNextState();
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression to the writer.
+        /// </summary>
+        /// <param name="regex">A BsonRegularExpression.</param>
+        public override void WriteRegularExpression(BsonRegularExpression regex)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteRegularExpression", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.RegularExpression);
+            WriteNameHelper();
+            _buffer.WriteCString(_binaryWriterSettings.Encoding, regex.Pattern);
+            _buffer.WriteCString(_binaryWriterSettings.Encoding, regex.Options);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON array to the writer.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteStartArray", BsonWriterState.Value);
+            }
+
+            base.WriteStartArray();
+            _buffer.WriteByte((byte)BsonType.Array);
+            WriteNameHelper();
+            _context = new BsonBinaryWriterContext(_context, ContextType.Array, _buffer.Position);
+            _buffer.WriteInt32(0); // reserve space for size
+
+            State = BsonWriterState.Value;
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON document to the writer.
+        /// </summary>
+        public override void WriteStartDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Initial && State != BsonWriterState.Value && State != BsonWriterState.ScopeDocument && State != BsonWriterState.Done)
+            {
+                ThrowInvalidState("WriteStartDocument", BsonWriterState.Initial, BsonWriterState.Value, BsonWriterState.ScopeDocument, BsonWriterState.Done);
+            }
+
+            base.WriteStartDocument();
+            if (State == BsonWriterState.Value)
+            {
+                _buffer.WriteByte((byte)BsonType.Document);
+                WriteNameHelper();
+            }
+	        _context = new BsonBinaryWriterContext(_context, ContextType.Document, _buffer.Position);
+            _buffer.WriteInt32(0); // reserve space for size
+
+            State = BsonWriterState.Name;
+        }
+
+        /// <summary>
+        /// Writes a BSON String to the writer.
+        /// </summary>
+        /// <param name="value">The String value.</param>
+        public override void WriteString(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteString", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.String);
+            WriteNameHelper();
+            _buffer.WriteString(_binaryWriterSettings.Encoding, value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Symbol to the writer.
+        /// </summary>
+        /// <param name="value">The symbol.</param>
+        public override void WriteSymbol(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteSymbol", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Symbol);
+            WriteNameHelper();
+            _buffer.WriteString(_binaryWriterSettings.Encoding, value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON timestamp to the writer.
+        /// </summary>
+        /// <param name="value">The combined timestamp/increment value.</param>
+        public override void WriteTimestamp(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteTimestamp", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Timestamp);
+            WriteNameHelper();
+            _buffer.WriteInt64(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON undefined to the writer.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonBinaryWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteUndefined", BsonWriterState.Value);
+            }
+
+            _buffer.WriteByte((byte)BsonType.Undefined);
+            WriteNameHelper();
+
+            State = GetNextState();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the writer.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Close();
+                if (_buffer != null)
+                {
+                    if (_disposeBuffer)
+                    {
+                        _buffer.Dispose();
+                    }
+                    _buffer = null;
+                }
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private void BackpatchSize()
+        {
+            int size = _buffer.Position - _context.StartPosition;
+            if (size > _maxDocumentSizeStack.Peek())
+            {
+                var message = string.Format("Size {0} is larger than MaxDocumentSize {1}.", size, _maxDocumentSizeStack.Peek());
+                throw new Exception(message);
+            }
+            _buffer.Backpatch(_context.StartPosition, size);
+        }
+
+        private BsonWriterState GetNextState()
+        {
+            if (_context.ContextType == ContextType.Array)
+            {
+                return BsonWriterState.Value;
+            }
+            else
+            {
+                return BsonWriterState.Name;
+            }
+        }
+
+        private void WriteNameHelper()
+        {
+            string name;
+            if (_context.ContextType == ContextType.Array)
+            {
+                name = (_context.Index++).ToString();
+            }
+            else
+            {
+                name = Name;
+            }
+
+            _buffer.WriteCString(__strictUtf8Encoding, name);
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriter.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 37f28baa6aba24042a448612e74b725a
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 59 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterContext.cs

@@ -0,0 +1,59 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    internal class BsonBinaryWriterContext
+    {
+        // private fields
+        private BsonBinaryWriterContext _parentContext;
+        private ContextType _contextType;
+        private int _startPosition;
+        private int _index; // used when contextType is Array
+
+        // constructors
+        internal BsonBinaryWriterContext(
+            BsonBinaryWriterContext parentContext,
+            ContextType contextType,
+            int startPosition)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _startPosition = startPosition;
+        }
+
+        // internal properties
+        internal BsonBinaryWriterContext ParentContext
+        {
+            get { return _parentContext; }
+        }
+
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        internal int StartPosition
+        {
+            get { return _startPosition; }
+        }
+
+        internal int Index
+        {
+            get { return _index; }
+            set { _index = value; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3b35a234249f7854381552ff7c0324fc
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 167 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs

@@ -0,0 +1,167 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Text;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonBinaryWriter.
+    /// </summary>
+    [Serializable]
+    public class BsonBinaryWriterSettings : BsonWriterSettings
+    {
+        // private static fields
+        private static BsonBinaryWriterSettings __defaults = null; // delay creation to pick up the latest default values
+
+        // private fields
+        private bool _closeOutput = false;
+        private UTF8Encoding _encoding = new UTF8Encoding(false, true);
+        private bool _fixOldBinarySubTypeOnOutput = true;
+        private int _maxDocumentSize = BsonDefaults.MaxDocumentSize;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryWriterSettings class.
+        /// </summary>
+        public BsonBinaryWriterSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonBinaryWriterSettings class.
+        /// </summary>
+        /// <param name="closeOutput">Whether to close the output stream when the writer is closed.</param>
+        /// <param name="fixOldBinarySubTypeOnOutput">Whether to fix old binary data subtype on output.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        /// <param name="maxDocumentSize">The max document size.</param>
+        [Obsolete("Use the no-argument constructor instead and set the properties.")]
+        public BsonBinaryWriterSettings(
+            bool closeOutput,
+            bool fixOldBinarySubTypeOnOutput,
+            GuidRepresentation guidRepresentation,
+            int maxDocumentSize)
+            : base(guidRepresentation)
+        {
+            _closeOutput = closeOutput;
+            _fixOldBinarySubTypeOnOutput = fixOldBinarySubTypeOnOutput;
+            _maxDocumentSize = maxDocumentSize;
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default BsonBinaryWriter settings.
+        /// </summary>
+        public static BsonBinaryWriterSettings Defaults
+        {
+            get
+            {
+                if (__defaults == null)
+                {
+                    __defaults = new BsonBinaryWriterSettings();
+                }
+                return __defaults;
+            }
+            set { __defaults = value; }
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets whether to close the output when the writer is closed.
+        /// </summary>
+        public bool CloseOutput
+        {
+            get { return _closeOutput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryWriterSettings is frozen."); }
+                _closeOutput = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the Encoding.
+        /// </summary>
+        public UTF8Encoding Encoding
+        {
+            get { return _encoding; }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryWriterSettings is frozen."); }
+                _encoding = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to fix the old binary data subtype on output.
+        /// </summary>
+        public bool FixOldBinarySubTypeOnOutput
+        {
+            get { return _fixOldBinarySubTypeOnOutput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryWriterSettings is frozen."); }
+                _fixOldBinarySubTypeOnOutput = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the max document size.
+        /// </summary>
+        public int MaxDocumentSize
+        {
+            get { return _maxDocumentSize; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("BsonBinaryWriterSettings is frozen."); }
+                _maxDocumentSize = value;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public new BsonBinaryWriterSettings Clone()
+        {
+            return (BsonBinaryWriterSettings)CloneImplementation();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected override BsonWriterSettings CloneImplementation()
+        {
+            var clone = new BsonBinaryWriterSettings
+            {
+                CloseOutput = _closeOutput,
+                Encoding = _encoding,
+                FixOldBinarySubTypeOnOutput = _fixOldBinarySubTypeOnOutput,
+                GuidRepresentation = GuidRepresentation,
+                MaxDocumentSize = _maxDocumentSize,
+                MaxSerializationDepth = MaxSerializationDepth
+            };
+            return clone;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d1f3818c03a5bdd4cb27717e8f268f73
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 804 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBuffer.cs

@@ -0,0 +1,804 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using System.Text;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a buffer for BSON encoded bytes.
+    /// </summary>
+    public class BsonBuffer : IDisposable
+    {
+        // private static fields
+        private static readonly string[] __asciiStringTable = BuildAsciiStringTable();
+        private static readonly bool[] __validBsonTypes = new bool[256];
+
+        // private fields
+        private bool _disposed = false;
+        private IByteBuffer _byteBuffer;
+        private bool _disposeByteBuffer;
+
+        // static constructor
+        static BsonBuffer()
+        {
+            foreach (BsonType bsonType in Enum.GetValues(typeof(BsonType)))
+            {
+                __validBsonTypes[(byte)bsonType] = true;
+            }
+        }
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonBuffer class.
+        /// </summary>
+        public BsonBuffer()
+            : this(new MultiChunkBuffer(BsonChunkPool.Default), true)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonBuffer" /> class.
+        /// </summary>
+        /// <param name="byteBuffer">The buffer.</param>
+        /// <param name="disposeByteBuffer">if set to <c>true</c> this BsonBuffer will own the byte buffer and when Dispose is called the byte buffer will be Disposed also.</param>
+        public BsonBuffer(IByteBuffer byteBuffer, bool disposeByteBuffer)
+        {
+            _byteBuffer = byteBuffer;
+            _disposeByteBuffer = disposeByteBuffer;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the byte buffer.
+        /// </summary>
+        /// <value>
+        /// The byte buffer.
+        /// </value>
+        public IByteBuffer ByteBuffer
+        {
+            get { return _byteBuffer; }
+        }
+
+        /// <summary>
+        /// Gets or sets the length of the data in the buffer.
+        /// </summary>
+        public int Length
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _byteBuffer.Length;
+            }
+            set
+            {
+                ThrowIfDisposed();
+                _byteBuffer.Length = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the current position in the buffer.
+        /// </summary>
+        public int Position
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _byteBuffer.Position;
+            }
+            set
+            {
+                ThrowIfDisposed();
+                _byteBuffer.Position = value;
+            }
+        }
+
+        // private static methods
+        private static string[] BuildAsciiStringTable()
+        {
+            var asciiStringTable = new string[128];
+
+            for (int i = 0; i < 128; ++i)
+            {
+                asciiStringTable[i] = new string((char)i, 1);
+            }
+
+            return asciiStringTable;
+        }
+
+        // public methods
+        /// <summary>
+        /// Backpatches the length of an object.
+        /// </summary>
+        /// <param name="position">The start position of the object.</param>
+        /// <param name="length">The length of the object.</param>
+        public void Backpatch(int position, int length)
+        {
+            ThrowIfDisposed();
+            var savedPosition = _byteBuffer.Position;
+            _byteBuffer.Position = position;
+            WriteInt32(length);
+            _byteBuffer.Position = savedPosition;
+        }
+
+        /// <summary>
+        /// Clears the data in the buffer.
+        /// </summary>
+        public void Clear()
+        {
+            ThrowIfDisposed();
+            _byteBuffer.Clear();
+        }
+
+        /// <summary>
+        /// Copies data from the buffer to a byte array.
+        /// </summary>
+        /// <param name="sourceOffset">The source offset in the buffer.</param>
+        /// <param name="destination">The destination byte array.</param>
+        /// <param name="destinationOffset">The destination offset in the byte array.</param>
+        /// <param name="count">The number of bytes to copy.</param>
+        [Obsolete("Use ReadBytes instead.")]
+        public void CopyTo(int sourceOffset, byte[] destination, int destinationOffset, int count)
+        {
+            ThrowIfDisposed();
+            var savedPosition = _byteBuffer.Position;
+            _byteBuffer.Position = sourceOffset;
+            _byteBuffer.ReadBytes(destination, destinationOffset, count);
+            _byteBuffer.Position = savedPosition;
+        }
+
+        /// <summary>
+        /// Disposes of any resources held by the buffer.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Loads the buffer from a Stream (the Stream must be positioned at a 4 byte length field).
+        /// </summary>
+        /// <param name="stream">The Stream.</param>
+        public void LoadFrom(Stream stream)
+        {
+            LoadFrom(stream, 4); // does not advance position
+            int length = ReadInt32(); // advances position 4 bytes
+            LoadFrom(stream, length - 4); // does not advance position
+            Position -= 4; // move back to just before the length field
+        }
+
+        /// <summary>
+        /// Loads the buffer from a Stream (leaving the position in the buffer unchanged).
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="count">The number of bytes to load.</param>
+        public void LoadFrom(Stream stream, int count)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.LoadFrom(stream, count); // does not advance position
+        }
+
+        /// <summary>
+        /// Peeks at the next byte in the buffer and returns it as a BsonType.
+        /// </summary>
+        /// <returns>A BsonType.</returns>
+        [Obsolete("Use ReadBsonType instead.")]
+        public BsonType PeekBsonType()
+        {
+            ThrowIfDisposed();
+            var value = ReadBsonType();
+            Position -= 1;
+            return value;
+        }
+
+        /// <summary>
+        /// Peeks at the next byte in the buffer.
+        /// </summary>
+        /// <returns>A Byte.</returns>
+        [Obsolete("Use ReadByte instead.")]
+        public byte PeekByte()
+        {
+            ThrowIfDisposed();
+            var value = ReadByte();
+            Position -= 1;
+            return value;
+        }
+
+        /// <summary>
+        /// Reads a BSON Boolean from the buffer.
+        /// </summary>
+        /// <returns>A Boolean.</returns>
+        public bool ReadBoolean()
+        {
+            ThrowIfDisposed();
+            return _byteBuffer.ReadByte() != 0;
+        }
+
+        /// <summary>
+        /// Reads a BSON type from the buffer.
+        /// </summary>
+        /// <returns>A BsonType.</returns>
+        public BsonType ReadBsonType()
+        {
+            ThrowIfDisposed();
+            var bsonType = (int)_byteBuffer.ReadByte();
+            if (!__validBsonTypes[bsonType])
+            {
+                string message = string.Format("Invalid BsonType {0}.", bsonType);
+                throw new Exception(message);
+            }
+            return (BsonType)bsonType;
+        }
+
+        /// <summary>
+        /// Reads a byte from the buffer.
+        /// </summary>
+        /// <returns>A Byte.</returns>
+        public byte ReadByte()
+        {
+            ThrowIfDisposed();
+            return _byteBuffer.ReadByte();
+        }
+
+        /// <summary>
+        /// Reads bytes from the buffer.
+        /// </summary>
+        /// <param name="count">The number of bytes to read.</param>
+        /// <returns>A byte array.</returns>
+        public byte[] ReadBytes(int count)
+        {
+            ThrowIfDisposed();
+            return _byteBuffer.ReadBytes(count);
+        }
+
+        /// <summary>
+        /// Reads a BSON Double from the buffer.
+        /// </summary>
+        /// <returns>A Double.</returns>
+        public double ReadDouble()
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.ReadBackingBytes(8);
+            if (segment.Count >= 8)
+            {
+                return BitConverter.ToDouble(segment.Array, segment.Offset);
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(8);
+                return BitConverter.ToDouble(bytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON Int32 from the reader.
+        /// </summary>
+        /// <returns>An Int32.</returns>
+        public int ReadInt32()
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.ReadBackingBytes(4);
+            if (segment.Count >= 4)
+            {
+                // for int only we come out ahead with this code vs using BitConverter
+                return
+                    ((int)segment.Array[segment.Offset + 0]) +
+                    ((int)segment.Array[segment.Offset + 1] << 8) +
+                    ((int)segment.Array[segment.Offset + 2] << 16) +
+                    ((int)segment.Array[segment.Offset + 3] << 24);
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(4);
+                return BitConverter.ToInt32(bytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON Int64 from the reader.
+        /// </summary>
+        /// <returns>An Int64.</returns>
+        public long ReadInt64()
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.ReadBackingBytes(8);
+            if (segment.Count >= 8)
+            {
+                return BitConverter.ToInt64(segment.Array, segment.Offset);
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(8);
+                return BitConverter.ToInt64(bytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <returns>An ObjectId.</returns>
+        public ObjectId ReadObjectId()
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.ReadBackingBytes(12);
+            if (segment.Count >= 12)
+            {
+                var bytes = segment.Array;
+                var offset = segment.Offset;
+                var timestamp = (bytes[offset + 0] << 24) + (bytes[offset + 1] << 16) + (bytes[offset + 2] << 8) + bytes[offset + 3];
+                var machine = (bytes[offset + 4] << 16) + (bytes[offset + 5] << 8) + bytes[offset + 6];
+                var pid = (short)((bytes[offset + 7] << 8) + bytes[offset + 8]);
+                var increment = (bytes[offset + 9] << 16) + (bytes[offset + 10] << 8) + bytes[offset + 11];
+                return new ObjectId(timestamp, machine, pid, increment);
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(12);
+                return new ObjectId(bytes);
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use ReadObjectId() instead.")]
+        public void ReadObjectId(out int timestamp, out int machine, out short pid, out int increment)
+        {
+            var objectId = ReadObjectId();
+            timestamp = objectId.Timestamp;
+            machine = objectId.Machine;
+            pid = objectId.Pid;
+            increment = objectId.Increment;
+        }
+
+        /// <summary>
+        /// Reads a BSON string from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        public string ReadString(UTF8Encoding encoding)
+        {
+            ThrowIfDisposed();
+            var length = ReadInt32(); // length including the null terminator
+            if (length <= 0)
+            {
+                var message = string.Format("Invalid string length: {0} (the length includes the null terminator so it must be greater than or equal to 1).", length);
+                throw new Exception(message);
+            }
+
+            string value;
+            byte finalByte;
+
+            var segment = _byteBuffer.ReadBackingBytes(length);
+            if (segment.Count >= length)
+            {
+                value = DecodeUtf8String(encoding, segment.Array, segment.Offset, length - 1);
+                finalByte = segment.Array[segment.Offset + length - 1];
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(length);
+                value = DecodeUtf8String(encoding, bytes, 0, length - 1);
+                finalByte = bytes[length - 1];
+            }
+
+            if (finalByte != 0)
+            {
+                throw new Exception("String is missing null terminator.");
+            }
+
+            return value;
+        }
+
+        /// <summary>
+        /// Reads a BSON CString from the reader (a null terminated string).
+        /// </summary>
+        /// <returns>A string.</returns>
+        public string ReadCString(UTF8Encoding encoding)
+        {
+            ThrowIfDisposed();
+
+            var nullPosition = _byteBuffer.FindNullByte();
+            if (nullPosition == -1)
+            {
+                throw new BsonSerializationException("Missing null terminator.");
+            }
+
+            return ReadCString(encoding, nullPosition);
+        }
+
+        /// <summary>
+        /// Reads an element name.
+        /// </summary>
+        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+        /// <param name="bsonTrie">An optional BsonTrie to use during decoding.</param>
+        /// <param name="found">Set to true if the string was found in the trie.</param>
+        /// <param name="value">Set to the value found in the trie; otherwise, null.</param>
+        /// <returns>A string.</returns>
+        public string ReadName<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
+        {
+            ThrowIfDisposed();
+            found = false;
+            value = default(TValue);
+
+            if (bsonTrie == null)
+            {
+                return ReadCString(new UTF8Encoding(false, true)); // always use strict encoding for names
+            }
+
+            var savedPosition = _byteBuffer.Position;
+            var bsonTrieNode = bsonTrie.Root;
+            while (true)
+            {
+                var keyByte = _byteBuffer.ReadByte();
+                if (keyByte == 0)
+                {
+                    if (bsonTrieNode.HasValue)
+                    {
+                        found = true;
+                        value = bsonTrieNode.Value;
+                        return bsonTrieNode.ElementName;
+                    }
+                    else
+                    {
+                        var nullPosition = _byteBuffer.Position - 1;
+                        _byteBuffer.Position = savedPosition;
+                        return ReadCString(new UTF8Encoding(false, true), nullPosition); // always use strict encoding for names
+                    }
+                }
+
+                bsonTrieNode = bsonTrieNode.GetChild(keyByte);
+                if (bsonTrieNode == null)
+                {
+                    var nullPosition = _byteBuffer.FindNullByte(); // starting from where we got so far
+                    _byteBuffer.Position = savedPosition;
+                    return ReadCString(new UTF8Encoding(false, true), nullPosition); // always use strict encoding for names
+                }
+            }
+        }
+
+        /// <summary>
+        /// Skips over bytes in the buffer (advances the position).
+        /// </summary>
+        /// <param name="count">The number of bytes to skip.</param>
+        public void Skip(int count)
+        {
+            _byteBuffer.Position += count;
+        }
+
+        /// <summary>
+        /// Skips over a CString in the buffer (advances the position).
+        /// </summary>
+        public void SkipCString()
+        {
+            ThrowIfDisposed();
+            var nullPosition = _byteBuffer.FindNullByte();
+            if (nullPosition == -1)
+            {
+                throw new Exception("String is missing null terminator");
+            }
+            _byteBuffer.Position = nullPosition + 1;
+        }
+
+        /// <summary>
+        /// Converts the buffer to a byte array.
+        /// </summary>
+        /// <returns>A byte array.</returns>
+        public byte[] ToByteArray()
+        {
+            ThrowIfDisposed();
+            var savedPosition = _byteBuffer.Position;
+            _byteBuffer.Position = 0;
+            var byteArray = _byteBuffer.ReadBytes(_byteBuffer.Length);
+            _byteBuffer.Position = savedPosition;
+            return byteArray;
+        }
+
+        /// <summary>
+        /// Writes a BSON Boolean to the buffer.
+        /// </summary>
+        /// <param name="value">The Boolean value.</param>
+        public void WriteBoolean(bool value)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteByte(value ? (byte)1 : (byte)0);
+        }
+
+        /// <summary>
+        /// Writes a byte to the buffer.
+        /// </summary>
+        /// <param name="value">A byte.</param>
+        public void WriteByte(byte value)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteByte(value);
+        }
+
+        /// <summary>
+        /// Writes bytes to the buffer.
+        /// </summary>
+        /// <param name="value">A byte array.</param>
+        public void WriteBytes(byte[] value)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteBytes(value);
+        }
+
+        /// <summary>
+        /// Writes a CString to the buffer.
+        /// </summary>
+        /// <param name="encoding">A UTF8 encoding.</param>
+        /// <param name="value">A string.</param>
+        public void WriteCString(UTF8Encoding encoding, string value)
+        {
+            if (value == null)
+            {
+                throw new ArgumentNullException("value");
+            }
+            if (value.IndexOf('\0') != -1)
+            {
+                throw new ArgumentException("CStrings cannot contain nulls.", "value");
+            }
+            ThrowIfDisposed();
+
+            var maxLength = encoding.GetMaxByteCount(value.Length) + 1;
+            var segment = _byteBuffer.WriteBackingBytes(maxLength);
+            if (segment.Count >= maxLength)
+            {
+                var length = encoding.GetBytes(value, 0, value.Length, segment.Array, segment.Offset);
+                segment.Array[segment.Offset + length] = 0;
+                _byteBuffer.Position += length + 1;
+            }
+            else
+            {
+                _byteBuffer.WriteBytes(encoding.GetBytes(value));
+                _byteBuffer.WriteByte(0);
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON Double to the buffer.
+        /// </summary>
+        /// <param name="value">The Double value.</param>
+        public void WriteDouble(double value)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteBytes(BitConverter.GetBytes(value));
+        }
+
+        /// <summary>
+        /// Writes a BSON Int32 to the buffer.
+        /// </summary>
+        /// <param name="value">The Int32 value.</param>
+        public void WriteInt32(int value)
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.WriteBackingBytes(4);
+            if (segment.Count >= 4)
+            {
+                segment.Array[segment.Offset + 0] = (byte)(value);
+                segment.Array[segment.Offset + 1] = (byte)(value >> 8);
+                segment.Array[segment.Offset + 2] = (byte)(value >> 16);
+                segment.Array[segment.Offset + 3] = (byte)(value >> 24);
+                _byteBuffer.Position += 4;
+            }
+            else
+            {
+                _byteBuffer.WriteBytes(BitConverter.GetBytes(value));
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON Int64 to the buffer.
+        /// </summary>
+        /// <param name="value">The Int64 value.</param>
+        public void WriteInt64(long value)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteBytes(BitConverter.GetBytes(value));
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the buffer.
+        /// </summary>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use WriteObjectId(ObjectId objectId) instead.")]
+        public void WriteObjectId(int timestamp, int machine, short pid, int increment)
+        {
+            var objectId = new ObjectId(timestamp, machine, pid, increment);
+            WriteObjectId(objectId);
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the buffer.
+        /// </summary>
+        /// <param name="objectId">The ObjectId.</param>
+        public void WriteObjectId(ObjectId objectId)
+        {
+            ThrowIfDisposed();
+
+            var segment = _byteBuffer.WriteBackingBytes(12);
+            if (segment.Count >= 12)
+            {
+                var timestamp = objectId.Timestamp;
+                var machine = objectId.Machine;
+                var pid = objectId.Pid;
+                var increment = objectId.Increment;
+                segment.Array[segment.Offset + 0] = (byte)(timestamp >> 24);
+                segment.Array[segment.Offset + 1] = (byte)(timestamp >> 16);
+                segment.Array[segment.Offset + 2] = (byte)(timestamp >> 8);
+                segment.Array[segment.Offset + 3] = (byte)(timestamp);
+                segment.Array[segment.Offset + 4] = (byte)(machine >> 16);
+                segment.Array[segment.Offset + 5] = (byte)(machine >> 8);
+                segment.Array[segment.Offset + 6] = (byte)(machine);
+                segment.Array[segment.Offset + 7] = (byte)(pid >> 8);
+                segment.Array[segment.Offset + 8] = (byte)(pid);
+                segment.Array[segment.Offset + 9] = (byte)(increment >> 16);
+                segment.Array[segment.Offset + 10] = (byte)(increment >> 8);
+                segment.Array[segment.Offset + 11] = (byte)(increment);
+                _byteBuffer.Position += 12;
+            }
+            else
+            {
+                _byteBuffer.WriteBytes(objectId.ToByteArray());
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON String to the buffer.
+        /// </summary>
+        /// <param name="encoding">A UTF8 encoding.</param>
+        /// <param name="value">The String value.</param>
+        public void WriteString(UTF8Encoding encoding, string value)
+        {
+            ThrowIfDisposed();
+
+            var maxLength = encoding.GetMaxByteCount(value.Length) + 5;
+            var segment = _byteBuffer.WriteBackingBytes(maxLength);
+            if (segment.Count >= maxLength)
+            {
+                var length = encoding.GetBytes(value, 0, value.Length, segment.Array, segment.Offset + 4);
+                var lengthPlusOne = length + 1;
+                segment.Array[segment.Offset + 0] = (byte)(lengthPlusOne); // now we know the length
+                segment.Array[segment.Offset + 1] = (byte)(lengthPlusOne >> 8);
+                segment.Array[segment.Offset + 2] = (byte)(lengthPlusOne >> 16);
+                segment.Array[segment.Offset + 3] = (byte)(lengthPlusOne >> 24);
+                segment.Array[segment.Offset + 4 + length] = 0;
+                _byteBuffer.Position += length + 5;
+            }
+            else
+            {
+                var bytes = encoding.GetBytes(value);
+                WriteInt32(bytes.Length + 1);
+                _byteBuffer.WriteBytes(bytes);
+                _byteBuffer.WriteByte(0);
+            }
+        }
+
+        /// <summary>
+        /// Writes all the data in the buffer to a Stream.
+        /// </summary>
+        /// <param name="stream">The Stream.</param>
+        public void WriteTo(Stream stream)
+        {
+            ThrowIfDisposed();
+            _byteBuffer.WriteTo(stream);
+        }
+
+        /// <summary>
+        /// Writes a 32-bit zero the the buffer.
+        /// </summary>
+        [Obsolete("Use WriteByte or WriteInt32 instead.")]
+        public void WriteZero()
+        {
+            ThrowIfDisposed();
+            WriteInt32(0);
+        }
+
+        // private static methods
+        private static string DecodeUtf8String(UTF8Encoding encoding, byte[] buffer, int index, int count)
+        {
+            switch (count)
+            {
+                // special case empty strings
+                case 0:
+                    return string.Empty;
+
+                // special case single character strings
+                case 1:
+                    var byte1 = (int)buffer[index];
+                    if (byte1 < __asciiStringTable.Length)
+                    {
+                        return __asciiStringTable[byte1];
+                    }
+                    break;
+            }
+
+            return encoding.GetString(buffer, index, count);
+        }
+
+        // protected methods
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    if (_byteBuffer != null)
+                    {
+                        if (_disposeByteBuffer)
+                        {
+                            _byteBuffer.Dispose();
+                        }
+                        _byteBuffer = null;
+                    }
+                }
+                _disposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Throws if disposed.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException"></exception>
+        protected void ThrowIfDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().Name);
+            }
+        }
+        
+        // private methods
+        private string ReadCString(UTF8Encoding encoding, int nullPosition)
+        {
+            if (nullPosition == -1)
+            {
+                throw new BsonSerializationException("Missing null terminator.");
+            }
+
+            var length = nullPosition - _byteBuffer.Position + 1;
+            var segment = _byteBuffer.ReadBackingBytes(length);
+            if (segment.Count >= length)
+            {
+                return DecodeUtf8String(encoding, segment.Array, segment.Offset, length - 1);
+            }
+            else
+            {
+                var bytes = _byteBuffer.ReadBytes(length);
+                return DecodeUtf8String(encoding, bytes, 0, length - 1);
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonBuffer.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 76a15caaa01dd164d881f9f477bd9e85
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 105 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunk.cs

@@ -0,0 +1,105 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON buffer chunk.
+    /// </summary>
+    public class BsonChunk
+    {
+        // private fields
+        private readonly byte[] _bytes;
+        private readonly BsonChunkPool _chunkPool;
+        private int _referenceCount;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonChunk"/> class.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        /// <param name="chunkPool">The chunk pool.</param>
+        /// <exception cref="System.ArgumentNullException">
+        /// bytes
+        /// or
+        /// pool
+        /// </exception>
+        public BsonChunk(byte[] bytes, BsonChunkPool chunkPool)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (chunkPool == null)
+            {
+                throw new ArgumentNullException("chunkPool");
+            }
+
+            _bytes = bytes;
+            _chunkPool = chunkPool;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the bytes.
+        /// </summary>
+        /// <value>
+        /// The bytes.
+        /// </value>
+        public byte[] Bytes
+        {
+            get { return _bytes; }
+        }
+
+        /// <summary>
+        /// Gets the reference count.
+        /// </summary>
+        /// <value>
+        /// The reference count.
+        /// </value>
+        public int ReferenceCount
+        {
+            get { return _referenceCount; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Decrements the reference count.
+        /// </summary>
+        /// <exception cref="BsonInternalException">Reference count is less than or equal to zero.</exception>
+        public void DecrementReferenceCount()
+        {
+            if (_referenceCount <= 0)
+            {
+                throw new BsonInternalException("Reference count is less than or equal to zero.");
+            }
+
+            if (--_referenceCount == 0 && _chunkPool != null)
+            {
+                _chunkPool.ReleaseChunk(this);
+            }
+        }
+
+        /// <summary>
+        /// Increments the reference count.
+        /// </summary>
+        public void IncrementReferenceCount()
+        {
+            _referenceCount++;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunk.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eb1e3fb44f0abd34ab80a1d41d74fde4
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 128 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunkPool.cs

@@ -0,0 +1,128 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a pool of chunks used by BsonBuffer.
+    /// </summary>
+    public class BsonChunkPool
+    {
+        // private static fields
+        private static BsonChunkPool __default = new BsonChunkPool(2048, 16 * 1024); // 32MiB of 16KiB chunks
+
+        // private fields
+        private readonly object _lock = new object();
+        private readonly Stack<BsonChunk> _chunks = new Stack<BsonChunk>();
+        private readonly int _maxPoolSize;
+        private readonly int _chunkSize;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonChunkPool"/> class.
+        /// </summary>
+        /// <param name="maxPoolSize">The maximum number of chunks to keep in the pool.</param>
+        /// <param name="chunkSize">The size of each chunk.</param>
+        public BsonChunkPool(int maxPoolSize, int chunkSize)
+        {
+            _maxPoolSize = maxPoolSize;
+            _chunkSize = chunkSize;
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets the default chunk pool.
+        /// </summary>
+        /// <value>
+        /// The default chunk pool.
+        /// </value>
+        public static BsonChunkPool Default
+        {
+            get { return __default; }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("Default");
+                }
+                __default = value;
+            }
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the chunk size.
+        /// </summary>
+        /// <value>
+        /// The chunk size.
+        /// </value>
+        public int ChunkSize
+        {
+            get { return _chunkSize; }
+        }
+
+        /// <summary>
+        /// Gets or sets the max pool size.
+        /// </summary>
+        public int MaxPoolSize
+        {
+            get { return _maxPoolSize; }
+        }
+
+        // internal methods
+        /// <summary>
+        /// Acquires a chunk.
+        /// </summary>
+        /// <returns></returns>
+        internal  BsonChunk AcquireChunk()
+        {
+            lock (_lock)
+            {
+                if (_chunks.Count > 0)
+                {
+                    return _chunks.Pop();
+                }
+            }
+
+            // release the lock before allocating memory
+            var bytes = new byte[_chunkSize];
+            return new BsonChunk(bytes, this);
+        }
+
+        /// <summary>
+        /// Releases a chunk.
+        /// </summary>
+        /// <param name="chunk">The chunk.</param>
+        internal void ReleaseChunk(BsonChunk chunk)
+        {
+            if (chunk.ReferenceCount != 0)
+            {
+                new BsonInternalException("A chunk is being returned to the pool and the reference count is not zero.");
+            }
+
+            lock (_lock)
+            {
+                if (_chunks.Count < _maxPoolSize)
+                {
+                    _chunks.Push(chunk);
+                }
+                // otherwise just let it get garbage collected
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonChunkPool.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 17dc04b25ed780d4f891c812fe7f0cf5
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 518 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReader.cs

@@ -0,0 +1,518 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON reader for a BsonDocument.
+    /// </summary>
+    public class BsonDocumentReader : BsonReader
+    {
+        // private fields
+	    private BsonDocumentReaderContext _context;
+        private BsonValue _currentValue;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentReader class.
+        /// </summary>
+        /// <param name="document">A BsonDocument.</param>
+        /// <param name="settings">The reader settings.</param>
+        public BsonDocumentReader(BsonDocument document, BsonDocumentReaderSettings settings)
+            : base(settings)
+        {
+            if (document == null)
+            {
+                throw new ArgumentNullException("document");
+            }
+
+            _context = new BsonDocumentReaderContext(null, ContextType.TopLevel, document);
+            _currentValue = document;
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the reader.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonReaderState.Closed)
+            {
+                State = BsonReaderState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Gets a bookmark to the reader's current position and state.
+        /// </summary>
+        /// <returns>A bookmark.</returns>
+        public override BsonReaderBookmark GetBookmark()
+        {
+            return new BsonDocumentReaderBookmark(State, CurrentBsonType, CurrentName, _context, _currentValue);
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A BsonBinaryData.</returns>
+        public override BsonBinaryData ReadBinaryData()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBinaryData", BsonType.Binary);
+
+            State = GetNextState();
+            return _currentValue.AsBsonBinaryData;
+        }
+
+        /// <summary>
+        /// Reads a BSON boolean from the reader.
+        /// </summary>
+        /// <returns>A Boolean.</returns>
+        public override bool ReadBoolean()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBoolean", BsonType.Boolean);
+            State = GetNextState();
+            return _currentValue.AsBoolean;
+        }
+
+        /// <summary>
+        /// Reads a BsonType from the reader.
+        /// </summary>
+        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+        /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
+        /// <param name="found">Set to true if a matching value was found in the trie.</param>
+        /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
+        /// <returns>A BsonType.</returns>
+        public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            found = false;
+            value = default(TValue);
+            if (State == BsonReaderState.Initial || State == BsonReaderState.ScopeDocument)
+            {
+                // there is an implied type of Document for the top level and for scope documents
+                CurrentBsonType = BsonType.Document;
+                State = BsonReaderState.Value;
+                return CurrentBsonType;
+            }
+            if (State != BsonReaderState.Type)
+            {
+                ThrowInvalidState("ReadBsonType", BsonReaderState.Type);
+            }
+
+            switch (_context.ContextType)
+            {
+                case ContextType.Array:
+                    _currentValue = _context.GetNextValue();
+                    if (_currentValue == null)
+                    {
+                        State = BsonReaderState.EndOfArray;
+                        return BsonType.EndOfDocument;
+                    }
+                    State = BsonReaderState.Value;
+                    break;
+                case ContextType.Document:
+                    var currentElement = _context.GetNextElement();
+                    if (currentElement == null)
+                    {
+                        State = BsonReaderState.EndOfDocument;
+                        return BsonType.EndOfDocument;
+                    }
+                    if (bsonTrie != null)
+                    {
+                        found = bsonTrie.TryGetValue(currentElement.Name, out value);
+                    }
+                    CurrentName = currentElement.Name;
+                    _currentValue = currentElement.Value;
+                    State = BsonReaderState.Name;
+                    break;
+                default:
+                    throw new BsonInternalException("Invalid ContextType.");
+            }
+
+            CurrentBsonType = _currentValue.BsonType;
+            return CurrentBsonType;
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A byte array.</returns>
+#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
+        public override byte[] ReadBytes()
+        {
+            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 {2}.", subType);
+                throw new Exception(message);
+            }
+
+            return binaryData.Bytes;
+        }
+#pragma warning restore 618
+
+        /// <summary>
+        /// Reads a BSON DateTime from the reader.
+        /// </summary>
+        /// <returns>The number of milliseconds since the Unix epoch.</returns>
+        public override long ReadDateTime()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDateTime", BsonType.DateTime);
+            State = GetNextState();
+            return _currentValue.AsBsonDateTime.MillisecondsSinceEpoch;
+        }
+
+        /// <summary>
+        /// Reads a BSON Double from the reader.
+        /// </summary>
+        /// <returns>A Double.</returns>
+        public override double ReadDouble()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDouble", BsonType.Double);
+            State = GetNextState();
+            return _currentValue.AsDouble;
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON array from the reader.
+        /// </summary>
+        public override void ReadEndArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Array)
+            {
+                ThrowInvalidContextType("ReadEndArray", _context.ContextType, ContextType.Array);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfArray if at end of array
+            }
+            if (State != BsonReaderState.EndOfArray)
+            {
+                ThrowInvalidState("ReadEndArray", BsonReaderState.EndOfArray);
+            }
+
+            _context = _context.PopContext();
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON document from the reader.
+        /// </summary>
+        public override void ReadEndDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
+            {
+                ThrowInvalidContextType("ReadEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfDocument if at end of document
+            }
+            if (State != BsonReaderState.EndOfDocument)
+            {
+                ThrowInvalidState("ReadEndDocument", BsonReaderState.EndOfDocument);
+            }
+
+            _context = _context.PopContext();
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON Int32 from the reader.
+        /// </summary>
+        /// <returns>An Int32.</returns>
+        public override int ReadInt32()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt32", BsonType.Int32);
+            State = GetNextState();
+            return _currentValue.AsInt32;
+        }
+
+        /// <summary>
+        /// Reads a BSON Int64 from the reader.
+        /// </summary>
+        /// <returns>An Int64.</returns>
+        public override long ReadInt64()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt64", BsonType.Int64);
+            State = GetNextState();
+            return _currentValue.AsInt64;
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScript()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScript", BsonType.JavaScript);
+            State = GetNextState();
+            return _currentValue.AsBsonJavaScript.Code;
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScriptWithScope()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScriptWithScope", BsonType.JavaScriptWithScope);
+
+            State = BsonReaderState.ScopeDocument;
+            return _currentValue.AsBsonJavaScriptWithScope.Code;
+        }
+
+        /// <summary>
+        /// Reads a BSON MaxKey from the reader.
+        /// </summary>
+        public override void ReadMaxKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMaxKey", BsonType.MaxKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON MinKey from the reader.
+        /// </summary>
+        public override void ReadMinKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMinKey", BsonType.MinKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON null from the reader.
+        /// </summary>
+        public override void ReadNull()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadNull", BsonType.Null);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <returns>An ObjectId.</returns>
+        public override ObjectId ReadObjectId()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadObjectId", BsonType.ObjectId);
+            State = GetNextState();
+            return _currentValue.AsObjectId;
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression from the reader.
+        /// </summary>
+        /// <returns>A BsonRegularExpression.</returns>
+        public override BsonRegularExpression ReadRegularExpression()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadRegularExpression", BsonType.RegularExpression);
+            State = GetNextState();
+            return _currentValue.AsBsonRegularExpression;
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON array.
+        /// </summary>
+        public override void ReadStartArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartArray", BsonType.Array);
+
+            var array = _currentValue.AsBsonArray;
+            _context = new BsonDocumentReaderContext(_context, ContextType.Array, array);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON document.
+        /// </summary>
+        public override void ReadStartDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartDocument", BsonType.Document);
+
+            BsonDocument document;
+            var script = _currentValue as BsonJavaScriptWithScope;
+            if (script != null)
+            {
+                document = script.Scope;
+            }
+            else
+            {
+                document = _currentValue.AsBsonDocument;
+            }
+            _context = new BsonDocumentReaderContext(_context, ContextType.Document, document);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads a BSON string from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        public override string ReadString()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadString", BsonType.String);
+            State = GetNextState();
+            return _currentValue.AsString;
+        }
+
+        /// <summary>
+        /// Reads a BSON symbol from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadSymbol()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadSymbol", BsonType.Symbol);
+            State = GetNextState();
+            return _currentValue.AsBsonSymbol.Name;
+        }
+
+        /// <summary>
+        /// Reads a BSON timestamp from the reader.
+        /// </summary>
+        /// <returns>The combined timestamp/increment.</returns>
+        public override long ReadTimestamp()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadTimestamp", BsonType.Timestamp);
+            State = GetNextState();
+            return _currentValue.AsBsonTimestamp.Value;
+        }
+
+        /// <summary>
+        /// Reads a BSON undefined from the reader.
+        /// </summary>
+        public override void ReadUndefined()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadUndefined", BsonType.Undefined);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Returns the reader to previously bookmarked position and state.
+        /// </summary>
+        /// <param name="bookmark">The bookmark.</param>
+        public override void ReturnToBookmark(BsonReaderBookmark bookmark)
+        {
+            var documentReaderBookmark = (BsonDocumentReaderBookmark)bookmark;
+            State = documentReaderBookmark.State;
+            CurrentBsonType = documentReaderBookmark.CurrentBsonType;
+            CurrentName = documentReaderBookmark.CurrentName;
+            _context = documentReaderBookmark.CloneContext();
+            _currentValue = documentReaderBookmark.CurrentValue;
+        }
+
+        /// <summary>
+        /// Skips the name (reader must be positioned on a name).
+        /// </summary>
+        public override void SkipName()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Name)
+            {
+                ThrowInvalidState("SkipName", BsonReaderState.Name);
+            }
+
+            State = BsonReaderState.Value;
+        }
+
+        /// <summary>
+        /// Skips the value (reader must be positioned on a value).
+        /// </summary>
+        public override void SkipValue()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Value)
+            {
+                ThrowInvalidState("SkipValue", BsonReaderState.Value);
+            }
+            State = BsonReaderState.Type;
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the reader.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                try
+                {
+                    Close();
+                }
+                catch { } // ignore exceptions
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private BsonReaderState GetNextState()
+        {
+            switch (_context.ContextType)
+            {
+                case ContextType.Array:
+                case ContextType.Document:
+                    return BsonReaderState.Type;
+                case ContextType.TopLevel:
+                    return BsonReaderState.Done;
+                default:
+                    throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReader.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c9065310af78ac6488437a7a791fb0a0
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 52 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderBookmark.cs

@@ -0,0 +1,52 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a bookmark that can be used to return a reader to the current position and state.
+    /// </summary>
+    public class BsonDocumentReaderBookmark : BsonReaderBookmark
+    {
+        // private fields
+        private BsonDocumentReaderContext _context;
+        private BsonValue _currentValue;
+
+        // constructors
+        internal BsonDocumentReaderBookmark(
+            BsonReaderState state,
+            BsonType currentBsonType,
+            string currentName,
+            BsonDocumentReaderContext context,
+            BsonValue currentValue)
+            : base(state, currentBsonType, currentName)
+        {
+            _context = context.Clone();
+            _currentValue = currentValue;
+        }
+
+        // internal properties
+        internal BsonValue CurrentValue
+        {
+            get { return _currentValue; }
+        }
+
+        // internal methods
+        internal BsonDocumentReaderContext CloneContext()
+        {
+            return _context.Clone();
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderBookmark.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0c4d1b9effbf1534d862573e264ed1a0
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 124 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderContext.cs

@@ -0,0 +1,124 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    internal class BsonDocumentReaderContext
+    {
+        // private fields
+        private BsonDocumentReaderContext _parentContext;
+        private ContextType _contextType;
+        private BsonDocument _document;
+        private BsonArray _array;
+        private int _index;
+
+        // constructors
+        internal BsonDocumentReaderContext(
+            BsonDocumentReaderContext parentContext,
+            ContextType contextType,
+            BsonArray array)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _array = array;
+        }
+
+        internal BsonDocumentReaderContext(
+            BsonDocumentReaderContext parentContext,
+            ContextType contextType,
+            BsonDocument document)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _document = document;
+        }
+
+        // used by Clone
+        private BsonDocumentReaderContext(
+            BsonDocumentReaderContext parentContext,
+            ContextType contextType,
+            BsonDocument document,
+            BsonArray array,
+            int index)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _document = document;
+            _array = array;
+            _index = index;
+        }
+
+        // internal properties
+        internal BsonArray Array
+        {
+            get { return _array; }
+        }
+
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        internal BsonDocument Document
+        {
+            get { return _document; }
+        }
+
+        internal int Index
+        {
+            get { return _index; }
+            set { _index = value; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the context.
+        /// </summary>
+        /// <returns>A clone of the context.</returns>
+        public BsonDocumentReaderContext Clone()
+        {
+            return new BsonDocumentReaderContext(_parentContext, _contextType, _document, _array, _index);
+        }
+
+        public BsonElement GetNextElement()
+        {
+            if (_index < _document.ElementCount)
+            {
+                return _document.GetElement(_index++);
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public BsonValue GetNextValue()
+        {
+            if (_index < _array.Count)
+            {
+                return _array[_index++];
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public BsonDocumentReaderContext PopContext()
+        {
+            return _parentContext;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: df22228a4352c004a88ce6f07b73bf38
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 88 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs

@@ -0,0 +1,88 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonDocumentReader.
+    /// </summary>
+    [Serializable]
+    public class BsonDocumentReaderSettings : BsonReaderSettings
+    {
+        // private static fields
+        private static BsonDocumentReaderSettings __defaults = null; // delay creation to pick up the latest default values
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentReaderSettings class.
+        /// </summary>
+        public BsonDocumentReaderSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentReaderSettings class.
+        /// </summary>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use the no-argument constructor instead and set the properties.")]
+        public BsonDocumentReaderSettings(GuidRepresentation guidRepresentation)
+            : base(guidRepresentation)
+        {
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default settings for a BsonDocumentReader.
+        /// </summary>
+        public static BsonDocumentReaderSettings Defaults
+        {
+            get
+            {
+                if (__defaults == null)
+                {
+                    __defaults = new BsonDocumentReaderSettings();
+                }
+                return __defaults;
+            }
+            set { __defaults = value; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public new BsonDocumentReaderSettings Clone()
+        {
+            return (BsonDocumentReaderSettings)CloneImplementation();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected override BsonReaderSettings CloneImplementation()
+        {
+            var clone = new BsonDocumentReaderSettings
+            {
+                GuidRepresentation = GuidRepresentation
+            };
+            return clone;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5f07677cfabfe5543810159d42cd14c1
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 525 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriter.cs

@@ -0,0 +1,525 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON writer to a BsonDocument.
+    /// </summary>
+    public class BsonDocumentWriter : BsonWriter
+    {
+        // private fields
+        private BsonDocument _topLevelDocument;
+	    private BsonDocumentWriterContext _context;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentWriter class.
+        /// </summary>
+        /// <param name="topLevelDocument">The document to write to (normally starts out as an empty document).</param>
+        /// <param name="settings">The settings.</param>
+        public BsonDocumentWriter(BsonDocument topLevelDocument, BsonDocumentWriterSettings settings)
+            : base(settings)
+        {
+            if (topLevelDocument == null)
+            {
+                throw new ArgumentNullException("topLevelDocument");
+            }
+
+            _topLevelDocument = topLevelDocument;
+	        _context = null;
+            State = BsonWriterState.Initial;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the top level BsonDocument.
+        /// </summary>
+        public BsonDocument TopLevelDocument
+        {
+            get { return _topLevelDocument; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the writer.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonWriterState.Closed)
+            {
+                _context = null;
+                State = BsonWriterState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Flushes any pending data to the output destination.
+        /// </summary>
+        public override void Flush()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        public override void WriteBinaryData(BsonBinaryData binaryData)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBinaryData", BsonWriterState.Value);
+            }
+
+            WriteValue(binaryData);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Boolean to the writer.
+        /// </summary>
+        /// <param name="value">The Boolean value.</param>
+        public override void WriteBoolean(bool value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBoolean", BsonWriterState.Value);
+            }
+
+            WriteValue(value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        public override void WriteBytes(byte[] bytes)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteBytes", BsonWriterState.Value);
+            }
+
+            WriteValue(new BsonBinaryData(bytes, BsonBinarySubType.Binary));
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON DateTime to the writer.
+        /// </summary>
+        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
+        public override void WriteDateTime(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteDateTime", BsonWriterState.Value);
+            }
+
+            WriteValue(new BsonDateTime(value));
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Double to the writer.
+        /// </summary>
+        /// <param name="value">The Double value.</param>
+        public override void WriteDouble(double value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteDouble", BsonWriterState.Value);
+            }
+
+            WriteValue(value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON array to the writer.
+        /// </summary>
+        public override void WriteEndArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteEndArray", BsonWriterState.Value);
+            }
+            if (_context.ContextType != ContextType.Array)
+            {
+                ThrowInvalidContextType("WriteEndArray", _context.ContextType, ContextType.Array);
+            }
+
+            base.WriteEndArray();
+            var array = _context.Array;
+            _context = _context.ParentContext;
+            WriteValue(array);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON document to the writer.
+        /// </summary>
+        public override void WriteEndDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Name)
+            {
+                ThrowInvalidState("WriteEndDocument", BsonWriterState.Name);
+            }
+            if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
+            {
+                ThrowInvalidContextType("WriteEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
+            }
+
+            base.WriteEndDocument();
+            if (_context.ContextType == ContextType.ScopeDocument)
+            {
+                var scope = _context.Document;
+                _context = _context.ParentContext;
+                var code = _context.Code;
+                _context = _context.ParentContext;
+                WriteValue(new BsonJavaScriptWithScope(code, scope));
+            }
+            else
+            {
+                var document = _context.Document;
+                _context = _context.ParentContext;
+                if (_context != null)
+                {
+                    WriteValue(document);
+                }
+            }
+
+            if (_context == null)
+            {
+                State = BsonWriterState.Done;
+            }
+            else
+            {
+                State = GetNextState();
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON Int32 to the writer.
+        /// </summary>
+        /// <param name="value">The Int32 value.</param>
+        public override void WriteInt32(int value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteInt32", BsonWriterState.Value);
+            }
+
+            WriteValue(value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Int64 to the writer.
+        /// </summary>
+        /// <param name="value">The Int64 value.</param>
+        public override void WriteInt64(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteInt64", BsonWriterState.Value);
+            }
+
+            WriteValue(value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer.
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScript(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteJavaScript", BsonWriterState.Value);
+            }
+
+            WriteValue(new BsonJavaScript(code));
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer (call WriteStartDocument to start writing the scope).
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScriptWithScope(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteJavaScriptWithScope", BsonWriterState.Value);
+            }
+
+            _context = new BsonDocumentWriterContext(_context, ContextType.JavaScriptWithScope, code);
+            State = BsonWriterState.ScopeDocument;
+        }
+
+        /// <summary>
+        /// Writes a BSON MaxKey to the writer.
+        /// </summary>
+        public override void WriteMaxKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteMaxKey", BsonWriterState.Value);
+            }
+
+            WriteValue(BsonMaxKey.Value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON MinKey to the writer.
+        /// </summary>
+        public override void WriteMinKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteMinKey", BsonWriterState.Value);
+            }
+
+            WriteValue(BsonMinKey.Value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the name of an element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public override void WriteName(string name)
+        {
+            base.WriteName(name);
+            _context.Name = name;
+        }
+
+        /// <summary>
+        /// Writes a BSON null to the writer.
+        /// </summary>
+        public override void WriteNull()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteNull", BsonWriterState.Value);
+            }
+
+            WriteValue(BsonNull.Value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the writer.
+        /// </summary>
+        /// <param name="objectId">The ObjectId.</param>
+        public override void WriteObjectId(ObjectId objectId)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteObjectId", BsonWriterState.Value);
+            }
+
+            WriteValue(objectId);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression to the writer.
+        /// </summary>
+        /// <param name="regex">A BsonRegularExpression.</param>
+        public override void WriteRegularExpression(BsonRegularExpression regex)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteRegularExpression", BsonWriterState.Value);
+            }
+
+            WriteValue(regex);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON array to the writer.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteStartArray", BsonWriterState.Value);
+            }
+
+            base.WriteStartArray();
+            _context = new BsonDocumentWriterContext(_context, ContextType.Array, new BsonArray());
+            State = BsonWriterState.Value;
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON document to the writer.
+        /// </summary>
+        public override void WriteStartDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Initial && State != BsonWriterState.Value && State != BsonWriterState.ScopeDocument && State != BsonWriterState.Done)
+            {
+                ThrowInvalidState("WriteStartDocument", BsonWriterState.Initial, BsonWriterState.Value, BsonWriterState.ScopeDocument, BsonWriterState.Done);
+            }
+
+            base.WriteStartDocument();
+            switch (State)
+            {
+                case BsonWriterState.Initial:
+                case BsonWriterState.Done:
+                    _context = new BsonDocumentWriterContext(null, ContextType.Document, _topLevelDocument);
+                    break;
+                case BsonWriterState.Value:
+                    _context = new BsonDocumentWriterContext(_context, ContextType.Document, new BsonDocument());
+                    break;
+                case BsonWriterState.ScopeDocument:
+                    _context = new BsonDocumentWriterContext(_context, ContextType.ScopeDocument, new BsonDocument());
+                    break;
+                default:
+                    throw new BsonInternalException("Unexpected state.");
+            }
+
+            State = BsonWriterState.Name;
+        }
+
+        /// <summary>
+        /// Writes a BSON String to the writer.
+        /// </summary>
+        /// <param name="value">The String value.</param>
+        public override void WriteString(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteString", BsonWriterState.Value);
+            }
+
+            WriteValue(value);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Symbol to the writer.
+        /// </summary>
+        /// <param name="value">The symbol.</param>
+        public override void WriteSymbol(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteSymbol", BsonWriterState.Value);
+            }
+
+            WriteValue(BsonSymbolTable.Lookup(value));
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON timestamp to the writer.
+        /// </summary>
+        /// <param name="value">The combined timestamp/increment value.</param>
+        public override void WriteTimestamp(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteTimestamp", BsonWriterState.Value);
+            }
+
+            WriteValue(new BsonTimestamp(value));
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON undefined to the writer.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            if (Disposed) { throw new ObjectDisposedException("BsonDocumentWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteUndefined", BsonWriterState.Value);
+            }
+
+            WriteValue(BsonUndefined.Value);
+            State = GetNextState();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the writer.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Close();
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private BsonWriterState GetNextState()
+        {
+            if (_context.ContextType == ContextType.Array)
+            {
+                return BsonWriterState.Value;
+            }
+            else
+            {
+                return BsonWriterState.Name;
+            }
+        }
+
+        private void WriteValue(BsonValue value)
+        {
+            if (_context.ContextType == ContextType.Array)
+            {
+                _context.Array.Add(value);
+            }
+            else
+            {
+                _context.Document.Add(_context.Name, value);
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriter.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f2ccaac556b49254ab977d71aeca4158
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 91 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterContext.cs

@@ -0,0 +1,91 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    internal class BsonDocumentWriterContext
+    {
+        // private fields
+        private BsonDocumentWriterContext _parentContext;
+        private ContextType _contextType;
+        private BsonDocument _document;
+        private BsonArray _array;
+        private string _code;
+        private string _name;
+
+        // constructors
+        internal BsonDocumentWriterContext(
+            BsonDocumentWriterContext parentContext,
+            ContextType contextType,
+            BsonDocument document)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _document = document;
+        }
+
+        internal BsonDocumentWriterContext(
+            BsonDocumentWriterContext parentContext,
+            ContextType contextType,
+            BsonArray array)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _array = array;
+        }
+
+        internal BsonDocumentWriterContext(
+            BsonDocumentWriterContext parentContext,
+            ContextType contextType,
+            string code)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _code = code;
+        }
+
+        // internal properties
+        internal BsonDocumentWriterContext ParentContext
+        {
+            get { return _parentContext; }
+        }
+
+        internal string Name
+        {
+            get { return _name; }
+            set { _name = value; }
+        }
+
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        internal BsonDocument Document
+        {
+            get { return _document; }
+        }
+
+        internal BsonArray Array
+        {
+            get { return _array; }
+        }
+
+        internal string Code
+        {
+            get { return _code; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 37b8623ed8ebfe9439c0e24b9268e1ab
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 89 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterSettings.cs

@@ -0,0 +1,89 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonDocumentWriter.
+    /// </summary>
+    [Serializable]
+    public class BsonDocumentWriterSettings : BsonWriterSettings
+    {
+        // private static fields
+        private static BsonDocumentWriterSettings __defaults = null; // delay creation to pick up the latest default values
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentWriterSettings class.
+        /// </summary>
+        public BsonDocumentWriterSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonDocumentWriterSettings class.
+        /// </summary>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use the no-argument constructor instead and set the properties.")]
+        public BsonDocumentWriterSettings(GuidRepresentation guidRepresentation)
+            : base(guidRepresentation)
+        {
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default BsonDocumentWriter settings.
+        /// </summary>
+        public static BsonDocumentWriterSettings Defaults
+        {
+            get
+            {
+                if (__defaults == null)
+                {
+                    __defaults = new BsonDocumentWriterSettings();
+                }
+                return __defaults;
+            }
+            set { __defaults = value; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public new BsonDocumentWriterSettings Clone()
+        {
+            return (BsonDocumentWriterSettings)CloneImplementation();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected override BsonWriterSettings CloneImplementation()
+        {
+            var clone = new BsonDocumentWriterSettings
+            {
+                GuidRepresentation = GuidRepresentation,
+                MaxSerializationDepth = MaxSerializationDepth
+            };
+            return clone;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonDocumentWriterSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3d0f2ed6022d7bd4d92d5551195afc62
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 959 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReader.cs

@@ -0,0 +1,959 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using System.Linq;
+using MongoDB.Bson.Serialization.Serializers;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON reader for some external format (see subclasses).
+    /// </summary>
+    public abstract class BsonReader : IDisposable
+    {
+        // private fields
+        private bool _disposed = false;
+        private BsonReaderSettings _settings;
+        private BsonReaderState _state;
+        private BsonType _currentBsonType;
+        private string _currentName;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonReader class.
+        /// </summary>
+        /// <param name="settings">The reader settings.</param>
+        protected BsonReader(BsonReaderSettings settings)
+        {
+            if (settings == null)
+            {
+                throw new ArgumentNullException("settings");
+            }
+
+            _settings = settings.FrozenCopy();
+            _state = BsonReaderState.Initial;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the current BsonType.
+        /// </summary>
+        public BsonType CurrentBsonType
+        {
+            get { return _currentBsonType; }
+            protected set { _currentBsonType = value; }
+        }
+
+        /// <summary>
+        /// Gets the settings of the reader.
+        /// </summary>
+        public BsonReaderSettings Settings
+        {
+            get { return _settings; }
+        }
+
+        /// <summary>
+        /// Gets the current state of the reader.
+        /// </summary>
+        public BsonReaderState State
+        {
+            get { return _state; }
+            protected set { _state = value; }
+        }
+
+        // protected properties
+        /// <summary>
+        /// Gets the current name.
+        /// </summary>
+        protected string CurrentName
+        {
+            get { return _currentName; }
+            set { _currentName = value; }
+        }
+
+        /// <summary>
+        /// Gets whether the BsonReader has been disposed.
+        /// </summary>
+        protected bool Disposed
+        {
+            get { return _disposed; }
+        }
+
+        // public static methods
+        /// <summary>
+        /// Creates a BsonReader for a BsonBuffer.
+        /// </summary>
+        /// <param name="buffer">The BsonBuffer.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(BsonBuffer buffer)
+        {
+            return Create(buffer, BsonBinaryReaderSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a BsonBuffer.
+        /// </summary>
+        /// <param name="buffer">The BsonBuffer.</param>
+        /// <param name="settings">Optional reader settings.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(BsonBuffer buffer, BsonBinaryReaderSettings settings)
+        {
+            return new BsonBinaryReader(buffer, false, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a BsonDocument.
+        /// </summary>
+        /// <param name="document">The BsonDocument.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(BsonDocument document)
+        {
+            return Create(document, BsonDocumentReaderSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a BsonDocument.
+        /// </summary>
+        /// <param name="document">The BsonDocument.</param>
+        /// <param name="settings">The settings.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(BsonDocument document, BsonDocumentReaderSettings settings)
+        {
+            return new BsonDocumentReader(document, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a JsonBuffer.
+        /// </summary>
+        /// <param name="buffer">The buffer.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(JsonBuffer buffer)
+        {
+            return Create(buffer, JsonReaderSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a JsonBuffer.
+        /// </summary>
+        /// <param name="buffer">The buffer.</param>
+        /// <param name="settings">The settings.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(JsonBuffer buffer, JsonReaderSettings settings)
+        {
+            return new JsonReader(buffer, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a BSON Stream.
+        /// </summary>
+        /// <param name="stream">The BSON Stream.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(Stream stream)
+        {
+            return Create(stream, BsonBinaryReaderSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a BSON Stream.
+        /// </summary>
+        /// <param name="stream">The BSON Stream.</param>
+        /// <param name="settings">Optional reader settings.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(Stream stream, BsonBinaryReaderSettings settings)
+        {
+            var byteBuffer = ByteBufferFactory.LoadFrom(stream);
+            byteBuffer.MakeReadOnly();
+            return new BsonBinaryReader(new BsonBuffer(byteBuffer, true), true, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a JSON string.
+        /// </summary>
+        /// <param name="json">The JSON string.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(string json)
+        {
+            var buffer = new JsonBuffer(json);
+            return Create(buffer);
+        }
+
+        /// <summary>
+        /// Creates a BsonReader for a JSON TextReader.
+        /// </summary>
+        /// <param name="textReader">The JSON TextReader.</param>
+        /// <returns>A BsonReader.</returns>
+        public static BsonReader Create(TextReader textReader)
+        {
+            var json = textReader.ReadToEnd();
+            return Create(json);
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the reader.
+        /// </summary>
+        public abstract void Close();
+
+        /// <summary>
+        /// Disposes of any resources used by the reader.
+        /// </summary>
+        public void Dispose()
+        {
+            if (!_disposed)
+            {
+                Dispose(true);
+                _disposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Positions the reader to an element by name.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>True if the element was found.</returns>
+        public bool FindElement(string name)
+        {
+            if (_disposed) { ThrowObjectDisposedException(); }
+            if (_state != BsonReaderState.Type)
+            {
+                ThrowInvalidState("FindElement", BsonReaderState.Type);
+            }
+
+	        while ((ReadBsonType()) != BsonType.EndOfDocument)
+            {
+                var elementName = ReadName();
+                if (elementName == name)
+                {
+                    return true;
+                }
+                SkipValue();
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Positions the reader to a string element by name.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>True if the element was found.</returns>
+        public string FindStringElement(string name)
+        {
+            if (_disposed) { ThrowObjectDisposedException(); }
+            if (_state != BsonReaderState.Type)
+            {
+                ThrowInvalidState("FindStringElement", BsonReaderState.Type);
+            }
+
+            BsonType bsonType;
+            while ((bsonType = ReadBsonType()) != BsonType.EndOfDocument)
+            {
+                var elementName = ReadName();
+                if (bsonType == BsonType.String && elementName == name)
+                {
+                    return ReadString();
+                }
+                else
+                {
+                    SkipValue();
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Gets a bookmark to the reader's current position and state.
+        /// </summary>
+        /// <returns>A bookmark.</returns>
+        public abstract BsonReaderBookmark GetBookmark();
+
+        /// <summary>
+        /// Gets the current BsonType (calls ReadBsonType if necessary).
+        /// </summary>
+        /// <returns>The current BsonType.</returns>
+        public BsonType GetCurrentBsonType()
+        {
+            if (_state == BsonReaderState.Initial || _state == BsonReaderState.Done || _state == BsonReaderState.ScopeDocument || _state == BsonReaderState.Type)
+            {
+                ReadBsonType();
+            }
+            if (_state != BsonReaderState.Value)
+            {
+                ThrowInvalidState("GetCurrentBsonType", BsonReaderState.Value);
+            }
+            return _currentBsonType;
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A BsonBinaryData.</returns>
+        public abstract BsonBinaryData ReadBinaryData();
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        [Obsolete("Use ReadBinaryData() instead.")]
+        public void ReadBinaryData(out byte[] bytes, out BsonBinarySubType subType)
+        {
+            GuidRepresentation guidRepresentation;
+            ReadBinaryData(out bytes, out subType, out guidRepresentation);
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use ReadBinaryData() instead.")]
+        public void ReadBinaryData(
+            out byte[] bytes,
+            out BsonBinarySubType subType,
+            out GuidRepresentation guidRepresentation)
+        {
+            var binaryData = ReadBinaryData();
+            bytes = binaryData.Bytes;
+            subType = binaryData.SubType;
+            guidRepresentation = binaryData.GuidRepresentation;
+        }
+
+        /// <summary>
+        /// Reads a BSON binary data element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A BsonBinaryData.</returns>
+        public BsonBinaryData ReadBinaryData(string name)
+        {
+            VerifyName(name);
+            return ReadBinaryData();
+        }
+
+        /// <summary>
+        /// Reads a BSON binary data element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        [Obsolete("Use ReadBinaryData(string name) instead.")]
+        public void ReadBinaryData(string name, out byte[] bytes, out BsonBinarySubType subType)
+        {
+            GuidRepresentation guidRepresentation;
+            ReadBinaryData(name, out bytes, out subType, out guidRepresentation);
+        }
+
+        /// <summary>
+        /// Reads a BSON binary data element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use ReadBinaryData(string name) instead.")]
+        public void ReadBinaryData(
+            string name,
+            out byte[] bytes,
+            out BsonBinarySubType subType,
+            out GuidRepresentation guidRepresentation)
+        {
+            VerifyName(name);
+            ReadBinaryData(out bytes, out subType, out guidRepresentation);
+        }
+
+        /// <summary>
+        /// Reads a BSON boolean from the reader.
+        /// </summary>
+        /// <returns>A Boolean.</returns>
+        public abstract bool ReadBoolean();
+
+        /// <summary>
+        /// Reads a BSON boolean element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A Boolean.</returns>
+        public bool ReadBoolean(string name)
+        {
+            VerifyName(name);
+            return ReadBoolean();
+        }
+
+        /// <summary>
+        /// Reads a BsonType from the reader.
+        /// </summary>
+        /// <returns>A BsonType.</returns>
+        public BsonType ReadBsonType()
+        {
+            bool found;
+            object value;
+            return ReadBsonType(null, out found, out value);
+        }
+
+        /// <summary>
+        /// Reads a BsonType from the reader.
+        /// </summary>
+        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+        /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
+        /// <param name="found">Set to true if a matching value was found in the trie.</param>
+        /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
+        /// <returns>A BsonType.</returns>
+        public abstract BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value);
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A byte array.</returns>
+        public abstract byte[] ReadBytes();
+
+        /// <summary>
+        /// Reads a BSON binary data element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A byte array.</returns>
+        public byte[] ReadBytes(string name)
+        {
+            VerifyName(name);
+            return ReadBytes();
+        }
+
+        /// <summary>
+        /// Reads a BSON DateTime from the reader.
+        /// </summary>
+        /// <returns>The number of milliseconds since the Unix epoch.</returns>
+        public abstract long ReadDateTime();
+
+        /// <summary>
+        /// Reads a BSON DateTime element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>The number of milliseconds since the Unix epoch.</returns>
+        public long ReadDateTime(string name)
+        {
+            VerifyName(name);
+            return ReadDateTime();
+        }
+
+        /// <summary>
+        /// Reads a BSON Double from the reader.
+        /// </summary>
+        /// <returns>A Double.</returns>
+        public abstract double ReadDouble();
+
+        /// <summary>
+        /// Reads a BSON Double element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A Double.</returns>
+        public double ReadDouble(string name)
+        {
+            VerifyName(name);
+            return ReadDouble();
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON array from the reader.
+        /// </summary>
+        public abstract void ReadEndArray();
+
+        /// <summary>
+        /// Reads the end of a BSON document from the reader.
+        /// </summary>
+        public abstract void ReadEndDocument();
+
+        /// <summary>
+        /// Reads a BSON Int32 from the reader.
+        /// </summary>
+        /// <returns>An Int32.</returns>
+        public abstract int ReadInt32();
+
+        /// <summary>
+        /// Reads a BSON Int32 element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>An Int32.</returns>
+        public int ReadInt32(string name)
+        {
+            VerifyName(name);
+            return ReadInt32();
+        }
+
+        /// <summary>
+        /// Reads a BSON Int64 from the reader.
+        /// </summary>
+        /// <returns>An Int64.</returns>
+        public abstract long ReadInt64();
+
+        /// <summary>
+        /// Reads a BSON Int64 element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>An Int64.</returns>
+        public long ReadInt64(string name)
+        {
+            VerifyName(name);
+            return ReadInt64();
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public abstract string ReadJavaScript();
+
+        /// <summary>
+        /// Reads a BSON JavaScript element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A string.</returns>
+        public string ReadJavaScript(string name)
+        {
+            VerifyName(name);
+            return ReadJavaScript();
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
+        /// </summary>
+        /// <returns>A string.</returns>
+        public abstract string ReadJavaScriptWithScope();
+
+        /// <summary>
+        /// Reads a BSON JavaScript with scope element from the reader (call ReadStartDocument next to read the scope).
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A string.</returns>
+        public string ReadJavaScriptWithScope(string name)
+        {
+            VerifyName(name);
+            return ReadJavaScriptWithScope();
+        }
+
+        /// <summary>
+        /// Reads a BSON MaxKey from the reader.
+        /// </summary>
+        public abstract void ReadMaxKey();
+
+        /// <summary>
+        /// Reads a BSON MaxKey element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void ReadMaxKey(string name)
+        {
+            VerifyName(name);
+            ReadMaxKey();
+        }
+
+        /// <summary>
+        /// Reads a BSON MinKey from the reader.
+        /// </summary>
+        public abstract void ReadMinKey();
+
+        /// <summary>
+        /// Reads a BSON MinKey element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void ReadMinKey(string name)
+        {
+            VerifyName(name);
+            ReadMinKey();
+        }
+
+        /// <summary>
+        /// Reads the name of an element from the reader.
+        /// </summary>
+        /// <returns>The name of the element.</returns>
+        public string ReadName()
+        {
+            if (_disposed) { ThrowObjectDisposedException(); }
+            if (_state == BsonReaderState.Type)
+            {
+                ReadBsonType();
+            }
+            if (_state != BsonReaderState.Name)
+            {
+                ThrowInvalidState("ReadName", BsonReaderState.Name);
+            }
+
+            _state = BsonReaderState.Value;
+            return _currentName;
+        }
+
+        /// <summary>
+        /// Reads the name of an element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void ReadName(string name)
+        {
+            VerifyName(name);
+        }
+
+        /// <summary>
+        /// Reads a BSON null from the reader.
+        /// </summary>
+        public abstract void ReadNull();
+
+        /// <summary>
+        /// Reads a BSON null element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void ReadNull(string name)
+        {
+            VerifyName(name);
+            ReadNull();
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <returns>An ObjectId.</returns>
+        public abstract ObjectId ReadObjectId();
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use ReadObjectId() instead.")]
+        public void ReadObjectId(out int timestamp, out int machine, out short pid, out int increment)
+        {
+            var objectId = ReadObjectId();
+            timestamp = objectId.Timestamp;
+            machine = objectId.Machine;
+            pid = objectId.Pid;
+            increment = objectId.Increment;
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>An ObjectId.</returns>
+        public ObjectId ReadObjectId(string name)
+        {
+            VerifyName(name);
+            return ReadObjectId();
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use ReadObjectId(string name) instead.")]
+        public void ReadObjectId(string name, out int timestamp, out int machine, out short pid, out int increment)
+        {
+            VerifyName(name);
+            ReadObjectId(out timestamp, out machine, out pid, out increment);
+        }
+
+        /// <summary>
+        /// Reads a raw BSON array.
+        /// </summary>
+        /// <returns>The raw BSON array.</returns>
+        public virtual IByteBuffer ReadRawBsonArray()
+        {
+            // overridden in BsonBinaryReader
+            var array = BsonArraySerializer.Instance.Deserialize(this, typeof(BsonArray), null);
+            using (var bsonWriter = new BsonBinaryWriter(new BsonBuffer(), true, BsonBinaryWriterSettings.Defaults))
+            {
+                bsonWriter.WriteStartDocument();
+                var startPosition = bsonWriter.Buffer.Position + 3; // just past BsonType, "x" and null byte
+                bsonWriter.WriteName("x");
+                BsonArraySerializer.Instance.Serialize(bsonWriter, typeof(BsonArray), array, null);
+                var endPosition = bsonWriter.Buffer.Position;
+                bsonWriter.WriteEndDocument();
+
+                var length = (int)(endPosition - startPosition);
+                bsonWriter.Buffer.Position = startPosition;
+                var bytes = bsonWriter.Buffer.ReadBytes(length);
+                return new ByteArrayBuffer(bytes, 0, length, true);
+            }
+        }
+
+        /// <summary>
+        /// Reads a raw BSON array.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <returns>
+        /// The raw BSON array.
+        /// </returns>
+        public IByteBuffer ReadRawBsonArray(string name)
+        {
+            VerifyName(name);
+            return ReadRawBsonArray();
+        }
+
+        /// <summary>
+        /// Reads a raw BSON document.
+        /// </summary>
+        /// <returns>The raw BSON document.</returns>
+        public virtual IByteBuffer ReadRawBsonDocument()
+        {
+            // overridden in BsonBinaryReader
+            var document = BsonDocumentSerializer.Instance.Deserialize(this, typeof(BsonDocument), null);
+            var bytes = document.ToBson();
+            return new ByteArrayBuffer(bytes, 0, bytes.Length, true);
+        }
+
+        /// <summary>
+        /// Reads a raw BSON document.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <returns>The raw BSON document.</returns>
+        public IByteBuffer ReadRawBsonDocument(string name)
+        {
+            VerifyName(name);
+            return ReadRawBsonDocument();
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression from the reader.
+        /// </summary>
+        /// <returns>A BsonRegularExpression.</returns>
+        public abstract BsonRegularExpression ReadRegularExpression();
+
+        /// <summary>
+        /// Reads a BSON regular expression from the reader.
+        /// </summary>
+        /// <param name="pattern">A regular expression pattern.</param>
+        /// <param name="options">A regular expression options.</param>
+        [Obsolete("Use ReadRegularExpression() instead.")]
+        public void ReadRegularExpression(out string pattern, out string options)
+        {
+            var regex = ReadRegularExpression();
+            pattern = regex.Pattern;
+            options = regex.Options;
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A BsonRegularExpression.</returns>
+        public BsonRegularExpression ReadRegularExpression(string name)
+        {
+            VerifyName(name);
+            return ReadRegularExpression();
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="pattern">A regular expression pattern.</param>
+        /// <param name="options">A regular expression options.</param>
+        [Obsolete("Use ReadRegularExpression(string name) instead.")]
+        public void ReadRegularExpression(string name, out string pattern, out string options)
+        {
+            VerifyName(name);
+            ReadRegularExpression(out pattern, out options);
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON array.
+        /// </summary>
+        public abstract void ReadStartArray();
+
+        /// <summary>
+        /// Reads the start of a BSON document.
+        /// </summary>
+        public abstract void ReadStartDocument();
+
+        /// <summary>
+        /// Reads a BSON string from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        public abstract string ReadString();
+
+        /// <summary>
+        /// Reads a BSON string element from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        /// <param name="name">The name of the element.</param>
+        public string ReadString(string name)
+        {
+            VerifyName(name);
+            return ReadString();
+        }
+
+        /// <summary>
+        /// Reads a BSON symbol from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public abstract string ReadSymbol();
+
+        /// <summary>
+        /// Reads a BSON symbol element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <returns>A string.</returns>
+        public string ReadSymbol(string name)
+        {
+            VerifyName(name);
+            return ReadSymbol();
+        }
+
+        /// <summary>
+        /// Reads a BSON timestamp from the reader.
+        /// </summary>
+        /// <returns>The combined timestamp/increment.</returns>
+        public abstract long ReadTimestamp();
+
+        /// <summary>
+        /// Reads a BSON timestamp element from the reader.
+        /// </summary>
+        /// <returns>The combined timestamp/increment.</returns>
+        /// <param name="name">The name of the element.</param>
+        public long ReadTimestamp(string name)
+        {
+            VerifyName(name);
+            return ReadTimestamp();
+        }
+
+        /// <summary>
+        /// Reads a BSON undefined from the reader.
+        /// </summary>
+        public abstract void ReadUndefined();
+
+        /// <summary>
+        /// Reads a BSON undefined element from the reader.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void ReadUndefined(string name)
+        {
+            VerifyName(name);
+            ReadUndefined();
+        }
+
+        /// <summary>
+        /// Returns the reader to previously bookmarked position and state.
+        /// </summary>
+        /// <param name="bookmark">The bookmark.</param>
+        public abstract void ReturnToBookmark(BsonReaderBookmark bookmark);
+
+        /// <summary>
+        /// Skips the name (reader must be positioned on a name).
+        /// </summary>
+        public abstract void SkipName();
+
+        /// <summary>
+        /// Skips the value (reader must be positioned on a value).
+        /// </summary>
+        public abstract void SkipValue();
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the reader.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+        }
+
+        /// <summary>
+        /// Throws an InvalidOperationException when the method called is not valid for the current ContextType.
+        /// </summary>
+        /// <param name="methodName">The name of the method.</param>
+        /// <param name="actualContextType">The actual ContextType.</param>
+        /// <param name="validContextTypes">The valid ContextTypes.</param>
+        protected void ThrowInvalidContextType(
+            string methodName,
+            ContextType actualContextType,
+            params ContextType[] validContextTypes)
+        {
+            var validContextTypesString = string.Join(" or ", validContextTypes.Select(c => c.ToString()).ToArray());
+            var message = string.Format(
+                "{0} can only be called when ContextType is {1}, not when ContextType is {2}.",
+                methodName, validContextTypesString, actualContextType);
+            throw new InvalidOperationException(message);
+        }
+
+        /// <summary>
+        /// Throws an InvalidOperationException when the method called is not valid for the current state.
+        /// </summary>
+        /// <param name="methodName">The name of the method.</param>
+        /// <param name="validStates">The valid states.</param>
+        protected void ThrowInvalidState(string methodName, params BsonReaderState[] validStates)
+        {
+            var validStatesString = string.Join(" or ", validStates.Select(s => s.ToString()).ToArray());
+            var message = string.Format(
+                "{0} can only be called when State is {1}, not when State is {2}.",
+                methodName, validStatesString, _state);
+            throw new InvalidOperationException(message);
+        }
+
+        /// <summary>
+        /// Throws an ObjectDisposedException.
+        /// </summary>
+        protected void ThrowObjectDisposedException()
+        {
+            throw new ObjectDisposedException(this.GetType().Name);
+        }
+
+        /// <summary>
+        /// Verifies the current state and BsonType of the reader.
+        /// </summary>
+        /// <param name="methodName">The name of the method calling this one.</param>
+        /// <param name="requiredBsonType">The required BSON type.</param>
+        protected void VerifyBsonType(string methodName, BsonType requiredBsonType)
+        {
+            if (_state == BsonReaderState.Initial || _state == BsonReaderState.ScopeDocument || _state == BsonReaderState.Type)
+            {
+                ReadBsonType();
+            }
+            if (_state == BsonReaderState.Name)
+            {
+                // ignore name
+                SkipName();
+            }
+            if (_state != BsonReaderState.Value)
+            {
+                ThrowInvalidState(methodName, BsonReaderState.Value);
+            }
+            if (_currentBsonType != requiredBsonType)
+            {
+                var message = string.Format(
+                    "{0} can only be called when CurrentBsonType is {1}, not when CurrentBsonType is {2}.",
+                    methodName, requiredBsonType, _currentBsonType);
+                throw new InvalidOperationException(message);
+            }
+        }
+
+        /// <summary>
+        /// Verifies the name of the current element.
+        /// </summary>
+        /// <param name="expectedName">The expected name.</param>
+        protected void VerifyName(string expectedName)
+        {
+            var actualName = ReadName();
+            if (actualName != expectedName)
+            {
+                var message = string.Format(
+                    "Expected element name to be '{0}', not '{1}'.",
+                    expectedName, actualName);
+                throw new Exception(message);
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReader.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 662f0b2d97caefa43b6ad1930686d562
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 67 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderBookmark.cs

@@ -0,0 +1,67 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a bookmark that can be used to return a reader to the current position and state.
+    /// </summary>
+    public abstract class BsonReaderBookmark
+    {
+        // private fields
+        private BsonReaderState _state;
+        private BsonType _currentBsonType;
+        private string _currentName;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonReaderBookmark class.
+        /// </summary>
+        /// <param name="state">The state of the reader.</param>
+        /// <param name="currentBsonType">The current BSON type.</param>
+        /// <param name="currentName">The name of the current element.</param>
+        protected BsonReaderBookmark(BsonReaderState state, BsonType currentBsonType, string currentName)
+        {
+            _state = state;
+            _currentBsonType = currentBsonType;
+            _currentName = currentName;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the current state of the reader.
+        /// </summary>
+        public BsonReaderState State
+        {
+            get { return _state; }
+        }
+
+        /// <summary>
+        /// Gets the current BsonType;
+        /// </summary>
+        public BsonType CurrentBsonType
+        {
+            get { return _currentBsonType; }
+        }
+
+        /// <summary>
+        /// Gets the name of the current element.
+        /// </summary>
+        public string CurrentName
+        {
+            get { return _currentName; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderBookmark.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d97bd6cc4d7465f4abc15b61bfcda3f8
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 121 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderSettings.cs

@@ -0,0 +1,121 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonReader.
+    /// </summary>
+    [Serializable]
+    public abstract class BsonReaderSettings
+    {
+        // private fields
+        private GuidRepresentation _guidRepresentation = BsonDefaults.GuidRepresentation;
+        private bool _isFrozen;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonReaderSettings class.
+        /// </summary>
+        protected BsonReaderSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonReaderSettings class.
+        /// </summary>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        protected BsonReaderSettings(GuidRepresentation guidRepresentation)
+        {
+            _guidRepresentation = guidRepresentation;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets the representation for Guids.
+        /// </summary>
+        public GuidRepresentation GuidRepresentation
+        {
+            get { return _guidRepresentation; }
+            set
+            {
+                if (_isFrozen) { ThrowFrozenException(); }
+                _guidRepresentation = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets whether the settings are frozen.
+        /// </summary>
+        public bool IsFrozen
+        {
+            get { return _isFrozen; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public BsonReaderSettings Clone()
+        {
+            return CloneImplementation();
+        }
+
+        /// <summary>
+        /// Freezes the settings.
+        /// </summary>
+        /// <returns>The frozen settings.</returns>
+        public BsonReaderSettings Freeze()
+        {
+            _isFrozen = true;
+            return this;
+        }
+
+        /// <summary>
+        /// Returns a frozen copy of the settings.
+        /// </summary>
+        /// <returns>A frozen copy of the settings.</returns>
+        public BsonReaderSettings FrozenCopy()
+        {
+            if (_isFrozen)
+            {
+                return this;
+            }
+            else
+            {
+                return Clone().Freeze();
+            }
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected abstract BsonReaderSettings CloneImplementation();
+
+        /// <summary>
+        /// Throws an InvalidOperationException when an attempt is made to change a setting after the settings are frozen.
+        /// </summary>
+        protected void ThrowFrozenException()
+        {
+            var message = string.Format("{0} is frozen.", this.GetType().Name);
+            throw new InvalidOperationException(message);
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8413e6dd4d4d0b34a9f4955c64a1b901
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 60 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderState.cs

@@ -0,0 +1,60 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents the state of a reader.
+    /// </summary>
+    public enum BsonReaderState
+    {
+        /// <summary>
+        /// The initial state.
+        /// </summary>
+        Initial,
+        /// <summary>
+        /// The reader is positioned at the type of an element or value.
+        /// </summary>
+        Type,
+        /// <summary>
+        /// The reader is positioned at the name of an element.
+        /// </summary>
+        Name,
+        /// <summary>
+        /// The reader is positioned at a value.
+        /// </summary>
+        Value,
+        /// <summary>
+        /// The reader is positioned at a scope document.
+        /// </summary>
+        ScopeDocument,
+        /// <summary>
+        /// The reader is positioned at the end of a document.
+        /// </summary>
+        EndOfDocument,
+        /// <summary>
+        /// The reader is positioned at the end of an array.
+        /// </summary>
+        EndOfArray,
+        /// <summary>
+        /// The reader has finished reading a document.
+        /// </summary>
+        Done,
+        /// <summary>
+        /// The reader is closed.
+        /// </summary>
+        Closed
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonReaderState.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8cba4338cf3ac114a971525e5bdc8429
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 307 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonTrie.cs

@@ -0,0 +1,307 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Text;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a mapping from a set of UTF8 encoded strings to a set of elementName/value pairs, implemented as a trie.
+    /// </summary>
+    /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+    public class BsonTrie<TValue>
+    {
+        // private static fields
+        private static readonly UTF8Encoding __utf8Encoding = new UTF8Encoding(false, true); // throw on invalid bytes
+
+        // private fields
+        private readonly BsonTrieNode<TValue> _root;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonTrie class.
+        /// </summary>
+        public BsonTrie()
+        {
+            _root = new BsonTrieNode<TValue>(0);
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the root node.
+        /// </summary>
+        public BsonTrieNode<TValue> Root
+        {
+            get
+            {
+                return _root;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Adds the specified elementName (after encoding as a UTF8 byte sequence) and value to the trie.
+        /// </summary>
+        /// <param name="elementName">The element name to add.</param>
+        /// <param name="value">The value to add. The value can be null for reference types.</param>
+        public void Add(string elementName, TValue value)
+        {
+            var keyBytes = __utf8Encoding.GetBytes(elementName);
+
+            var node = _root;
+            foreach (var keyByte in keyBytes)
+            {
+                var child = node.GetChild(keyByte);
+                if (child == null)
+                {
+                    child = new BsonTrieNode<TValue>(keyByte);
+                    node.AddChild(child);
+                }
+                node = child;
+            }
+
+            node.SetValue(elementName, value);
+        }
+
+        /// <summary>
+        /// Gets the value associated with the specified element name.
+        /// </summary>
+        /// <param name="elementName">The element name.</param>
+        /// <param name="value">
+        /// When this method returns, contains the value associated with the specified element name, if the key is found;
+        /// otherwise, the default value for the type of the value parameter. This parameter is passed unitialized.
+        /// </param>
+        /// <returns>True if the value was found; otherwise, false.</returns>
+        public bool TryGetValue(string elementName, out TValue value)
+        {
+            var keyBytes = __utf8Encoding.GetBytes(elementName);
+
+            var node = _root;
+            for (var i = 0; i < keyBytes.Length; i++)
+            {
+                node = node.GetChild(keyBytes[i]);
+                if (node == null)
+                {
+                    value = default(TValue);
+                    return false;
+                }
+            }
+
+            if (!node.HasValue)
+            {
+                value = default(TValue);
+                return false;
+            }
+
+            value = node.Value;
+            return true;
+        }
+    }
+
+    /// <summary>
+    /// Represents a node in a BsonTrie.
+    /// </summary>
+    /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+    public sealed class BsonTrieNode<TValue>
+    {
+        // private fields
+        private readonly byte _keyByte;
+        private string _elementName;
+        private TValue _value;
+        private BsonTrieNode<TValue> _onlyChild; // used when there is only one child
+        private BsonTrieNode<TValue>[] _children; // used when there are two or more children
+        private byte[] _childrenIndexes; // maps key bytes into indexes into the _children array
+        private byte _minChildKeyByte; // key byte value of first element in _childrenIndexes
+
+        // constructors
+        internal BsonTrieNode(byte keyByte)
+        {
+            _keyByte = keyByte;
+        }
+
+        /// <summary>
+        /// Gets whether this node has a value.
+        /// </summary>
+        public bool HasValue
+        {
+            get
+            {
+                return _elementName != null;
+            }
+        }
+
+        /// <summary>
+        /// Gets the element name for this node.
+        /// </summary>
+        public string ElementName
+        {
+            get
+            {
+                if (_elementName == null)
+                {
+                    throw new InvalidOperationException("BsonTrieNode doesn't have a value.");
+                }
+
+                return _elementName;
+            }
+        }
+
+        /// <summary>
+        /// Gets the value for this node.
+        /// </summary>
+        public TValue Value
+        {
+            get
+            {
+                if (_elementName == null)
+                {
+                    throw new InvalidOperationException("BsonTrieNode doesn't have a value.");
+                }
+
+                return _value;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Gets the child of this node for a given key byte.
+        /// </summary>
+        /// <param name="keyByte">The key byte.</param>
+        /// <returns>The child node if it exists; otherwise, null.</returns>
+        public BsonTrieNode<TValue> GetChild(byte keyByte)
+        {
+            if (_onlyChild != null)
+            {
+                // optimization for nodes that have only one child
+                if (_onlyChild._keyByte == keyByte)
+                {
+                    return _onlyChild;
+                }
+            }
+            else if (_children != null)
+            {
+                var index = (uint)((int)keyByte - _minChildKeyByte);
+                if (index < _childrenIndexes.Length)
+                {
+                    index = _childrenIndexes[index];
+                    if (index < _children.Length)
+                    {
+                        return _children[index];
+                    }
+                }
+            }
+            return null;
+        }
+
+        // internal methods
+        internal void AddChild(BsonTrieNode<TValue> child)
+        {
+            if (GetChild(child._keyByte) != null)
+            {
+                throw new ArgumentException("BsonTrieNode already contains a child with the same keyByte.");
+            }
+
+            if (_children != null)
+            {
+                // add a new child to the existing _children
+                var children = new BsonTrieNode<TValue>[_children.Length + 1];
+                Array.Copy(_children, children, _children.Length);
+                children[children.Length - 1] = child;
+
+                var childrenIndexes = _childrenIndexes;
+                var minChildKeyByte = _minChildKeyByte;
+                var maxChildKeyByte = _minChildKeyByte + _childrenIndexes.Length - 1;
+
+                // if new keyByte doesn't fall within existing min/max range expand the range
+                if (child._keyByte < minChildKeyByte)
+                {
+                    // grow the indexes on the min side
+                    minChildKeyByte = child._keyByte;
+                    childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
+                    var sizeDelta = childrenIndexes.Length - _childrenIndexes.Length;
+                    for (var i = 0; i < sizeDelta; i++)
+                    {
+                        childrenIndexes[i] = 255;
+                    }
+                    Array.Copy(_childrenIndexes, 0, childrenIndexes, sizeDelta, _childrenIndexes.Length);
+                }
+                else if (child._keyByte > maxChildKeyByte)
+                {
+                    // grow the indexes on the max side
+                    maxChildKeyByte = child._keyByte;
+                    childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
+	                Array.Copy(_childrenIndexes, 0, childrenIndexes, 0, _childrenIndexes.Length);
+                    for (var i = _childrenIndexes.Length; i < childrenIndexes.Length; i++)
+                    {
+                        childrenIndexes[i] = 255;
+                    }
+                }
+                childrenIndexes[child._keyByte - minChildKeyByte] = (byte)(children.Length - 1);
+
+                _children = children;
+                _childrenIndexes = childrenIndexes;
+                _minChildKeyByte = minChildKeyByte;
+            }
+            else if (_onlyChild != null)
+            {
+                // switch from having an _onlyChild to having two _children
+                var children = new BsonTrieNode<TValue>[2];
+                children[0] = _onlyChild;
+                children[1] = child;
+
+                var minChildKeyByte = _onlyChild._keyByte;
+                var maxChildKeyByte = child._keyByte;
+                if (minChildKeyByte > maxChildKeyByte)
+                {
+                    minChildKeyByte = child._keyByte;
+                    maxChildKeyByte = _onlyChild._keyByte;
+                }
+
+                var childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
+                for (var i = 0; i < childrenIndexes.Length; i++)
+                {
+                    childrenIndexes[i] = 255;
+                }
+                childrenIndexes[_onlyChild._keyByte - minChildKeyByte] = 0;
+                childrenIndexes[child._keyByte - minChildKeyByte] = 1;
+
+                _onlyChild = null;
+                _children = children;
+                _childrenIndexes = childrenIndexes;
+                _minChildKeyByte = minChildKeyByte;
+            }
+            else
+            {
+                _onlyChild = child;
+            }
+        }
+
+        internal void SetValue(string elementName, TValue value)
+        {
+            if (elementName == null)
+            {
+                throw new ArgumentNullException("elementName");
+            }
+            if (_elementName != null)
+            {
+                throw new InvalidOperationException("BsonTrieNode already has a value.");
+            }
+
+            _elementName = elementName;
+            _value = value;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonTrie.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a7f2044749d0ddc4c8b5263f565a867e
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 910 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriter.cs

@@ -0,0 +1,910 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using System.Linq;
+using MongoDB.Bson.Serialization;
+using MongoDB.Bson.Serialization.Serializers;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON writer for some external format (see subclasses).
+    /// </summary>
+    public abstract class BsonWriter : IDisposable
+    {
+        // private fields
+        private bool _disposed = false;
+        private BsonWriterSettings _settings;
+        private BsonWriterState _state;
+        private string _name;
+        private bool _checkElementNames;
+        private bool _checkUpdateDocument;
+        private int _serializationDepth;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonWriter class.
+        /// </summary>
+        /// <param name="settings">The writer settings.</param>
+        protected BsonWriter(BsonWriterSettings settings)
+        {
+            if (settings == null)
+            {
+                throw new ArgumentNullException("settings");
+            }
+
+            _settings = settings.FrozenCopy();
+            _state = BsonWriterState.Initial;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets whether to check element names (no periods or leading $).
+        /// </summary>
+        public bool CheckElementNames
+        {
+            get { return _checkElementNames; }
+            set { _checkElementNames = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to check an update document (turns CheckElementNames on if first element name does *not* start with $).
+        /// </summary>
+        public bool CheckUpdateDocument
+        {
+            get { return _checkUpdateDocument; }
+            set { _checkUpdateDocument = value; }
+        }
+
+        /// <summary>
+        /// Gets the current serialization depth.
+        /// </summary>
+        public int SerializationDepth
+        {
+            get { return _serializationDepth; }
+        }
+
+        /// <summary>
+        /// Gets the settings of the writer.
+        /// </summary>
+        public BsonWriterSettings Settings
+        {
+            get { return _settings; }
+        }
+
+        /// <summary>
+        /// Gets the current state of the writer.
+        /// </summary>
+        public BsonWriterState State
+        {
+            get { return _state; }
+            protected set { _state = value; }
+        }
+
+        // protected properties
+        /// <summary>
+        /// Gets whether the BsonWriter has been disposed.
+        /// </summary>
+        public bool Disposed
+        {
+            get { return _disposed; }
+        }
+
+        // protected properties
+        /// <summary>
+        /// Gets the name of the element being written.
+        /// </summary>
+        protected string Name
+        {
+            get { return _name; }
+        }
+
+        // public static methods
+        /// <summary>
+        /// Creates a BsonWriter to a BsonBuffer.
+        /// </summary>
+        /// <param name="settings">Optional BsonBinaryWriterSettings.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(BsonBinaryWriterSettings settings)
+        {
+            return new BsonBinaryWriter(null, null, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BsonBuffer.
+        /// </summary>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(BsonBuffer buffer)
+        {
+            return new BsonBinaryWriter(null, buffer, BsonBinaryWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BsonBuffer.
+        /// </summary>
+        /// <param name="buffer">A BsonBuffer.</param>
+        /// <param name="settings">Optional BsonBinaryWriterSettings.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(BsonBuffer buffer, BsonBinaryWriterSettings settings)
+        {
+            return new BsonBinaryWriter(null, buffer, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BsonDocument.
+        /// </summary>
+        /// <param name="document">A BsonDocument.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(BsonDocument document)
+        {
+            return Create(document, BsonDocumentWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BsonDocument.
+        /// </summary>
+        /// <param name="document">A BsonDocument.</param>
+        /// <param name="settings">The settings.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(BsonDocument document, BsonDocumentWriterSettings settings)
+        {
+            return new BsonDocumentWriter(document, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BSON Stream.
+        /// </summary>
+        /// <param name="stream">A Stream.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(Stream stream)
+        {
+            return Create(stream, BsonBinaryWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a BSON Stream.
+        /// </summary>
+        /// <param name="stream">A Stream.</param>
+        /// <param name="settings">Optional BsonBinaryWriterSettings.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(Stream stream, BsonBinaryWriterSettings settings)
+        {
+            return new BsonBinaryWriter(stream, null, settings);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a JSON TextWriter.
+        /// </summary>
+        /// <param name="writer">A TextWriter.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(TextWriter writer)
+        {
+            return new JsonWriter(writer, JsonWriterSettings.Defaults);
+        }
+
+        /// <summary>
+        /// Creates a BsonWriter to a JSON TextWriter.
+        /// </summary>
+        /// <param name="writer">A TextWriter.</param>
+        /// <param name="settings">Optional JsonWriterSettings.</param>
+        /// <returns>A BsonWriter.</returns>
+        public static BsonWriter Create(TextWriter writer, JsonWriterSettings settings)
+        {
+            return new JsonWriter(writer, settings);
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the writer.
+        /// </summary>
+        public abstract void Close();
+
+        /// <summary>
+        /// Disposes of any resources used by the writer.
+        /// </summary>
+        public void Dispose()
+        {
+            if (!_disposed)
+            {
+                Dispose(true);
+                _disposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Flushes any pending data to the output destination.
+        /// </summary>
+        public abstract void Flush();
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        public abstract void WriteBinaryData(BsonBinaryData binaryData);
+
+        /// <summary>
+        /// Writes a BSON binary data element to the writer.
+        /// </summary>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        [Obsolete("Use WriteBinaryData(BsonBinaryData binaryData) instead.")]
+        public void WriteBinaryData(byte[] bytes, BsonBinarySubType subType)
+        {
+            var guidRepresentation = (subType == BsonBinarySubType.UuidStandard) ? GuidRepresentation.Standard : GuidRepresentation.Unspecified;
+            WriteBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        /// <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 respresentation for Guids.</param>
+        [Obsolete("Use WriteBinaryData(BsonBinaryData binaryData) instead.")]
+        public void WriteBinaryData(
+            byte[] bytes,
+            BsonBinarySubType subType,
+            GuidRepresentation guidRepresentation)
+        {
+            var binaryData = new BsonBinaryData(bytes, subType, guidRepresentation);
+            WriteBinaryData(binaryData);
+        }
+
+        /// <summary>
+        /// Writes a BSON binary data element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="binaryData">The binary data.</param>
+        public void WriteBinaryData(string name, BsonBinaryData binaryData)
+        {
+            WriteName(name);
+            WriteBinaryData(binaryData);
+        }
+
+        /// <summary>
+        /// Writes a BSON binary data element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        [Obsolete("Use WriteBinaryData(string name, BsonBinaryData binaryData) instead.")]
+        public void WriteBinaryData(string name, byte[] bytes, BsonBinarySubType subType)
+        {
+            WriteName(name);
+            WriteBinaryData(bytes, subType);
+        }
+
+        /// <summary>
+        /// Writes a BSON binary data element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="bytes">The binary data.</param>
+        /// <param name="subType">The binary data subtype.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use WriteBinaryData(string name, BsonBinaryData binaryData) instead.")]
+        public void WriteBinaryData(
+            string name,
+            byte[] bytes,
+            BsonBinarySubType subType,
+            GuidRepresentation guidRepresentation)
+        {
+            WriteName(name);
+            WriteBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        /// <summary>
+        /// Writes a BSON Boolean to the writer.
+        /// </summary>
+        /// <param name="value">The Boolean value.</param>
+        public abstract void WriteBoolean(bool value);
+
+        /// <summary>
+        /// Writes a BSON Boolean element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The Boolean value.</param>
+        public void WriteBoolean(string name, bool value)
+        {
+            WriteName(name);
+            WriteBoolean(value);
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        public abstract void WriteBytes(byte[] bytes);
+
+        /// <summary>
+        /// Writes a BSON binary data element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="bytes">The bytes.</param>
+        public void WriteBytes(string name, byte[] bytes)
+        {
+            WriteName(name);
+            WriteBytes(bytes);
+        }
+
+        /// <summary>
+        /// Writes a BSON DateTime to the writer.
+        /// </summary>
+        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
+        public abstract void WriteDateTime(long value);
+
+        /// <summary>
+        /// Writes a BSON DateTime element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
+        public void WriteDateTime(string name, long value)
+        {
+            WriteName(name);
+            WriteDateTime(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON Double to the writer.
+        /// </summary>
+        /// <param name="value">The Double value.</param>
+        public abstract void WriteDouble(double value);
+
+        /// <summary>
+        /// Writes a BSON Double element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The Double value.</param>
+        public void WriteDouble(string name, double value)
+        {
+            WriteName(name);
+            WriteDouble(value);
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON array to the writer.
+        /// </summary>
+        public virtual void WriteEndArray()
+        {
+            _serializationDepth--;
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON document to the writer.
+        /// </summary>
+        public virtual void WriteEndDocument()
+        {
+            _serializationDepth--;
+        }
+
+        /// <summary>
+        /// Writes a BSON Int32 to the writer.
+        /// </summary>
+        /// <param name="value">The Int32 value.</param>
+        public abstract void WriteInt32(int value);
+
+        /// <summary>
+        /// Writes a BSON Int32 element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The Int32 value.</param>
+        public void WriteInt32(string name, int value)
+        {
+            WriteName(name);
+            WriteInt32(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON Int64 to the writer.
+        /// </summary>
+        /// <param name="value">The Int64 value.</param>
+        public abstract void WriteInt64(long value);
+
+        /// <summary>
+        /// Writes a BSON Int64 element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The Int64 value.</param>
+        public void WriteInt64(string name, long value)
+        {
+            WriteName(name);
+            WriteInt64(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer.
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public abstract void WriteJavaScript(string code);
+
+        /// <summary>
+        /// Writes a BSON JavaScript element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="code">The JavaScript code.</param>
+        public void WriteJavaScript(string name, string code)
+        {
+            WriteName(name);
+            WriteJavaScript(code);
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer (call WriteStartDocument to start writing the scope).
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public abstract void WriteJavaScriptWithScope(string code);
+
+        /// <summary>
+        /// Writes a BSON JavaScript element to the writer (call WriteStartDocument to start writing the scope).
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="code">The JavaScript code.</param>
+        public void WriteJavaScriptWithScope(string name, string code)
+        {
+            WriteName(name);
+            WriteJavaScriptWithScope(code);
+        }
+
+        /// <summary>
+        /// Writes a BSON MaxKey to the writer.
+        /// </summary>
+        public abstract void WriteMaxKey();
+
+        /// <summary>
+        /// Writes a BSON MaxKey element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteMaxKey(string name)
+        {
+            WriteName(name);
+            WriteMaxKey();
+        }
+
+        /// <summary>
+        /// Writes a BSON MinKey to the writer.
+        /// </summary>
+        public abstract void WriteMinKey();
+
+        /// <summary>
+        /// Writes a BSON MinKey element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteMinKey(string name)
+        {
+            WriteName(name);
+            WriteMinKey();
+        }
+
+        /// <summary>
+        /// Writes the name of an element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public virtual void WriteName(string name)
+        {
+            if (name == null)
+            {
+                throw new ArgumentNullException("name");
+            }
+            if (name.IndexOf('\0') != -1)
+            {
+                throw new ArgumentException("Element names cannot contain nulls.", "name");
+            }
+            if (_disposed) { throw new ObjectDisposedException(this.GetType().Name); }
+            if (_state != BsonWriterState.Name)
+            {
+                ThrowInvalidState("WriteName", BsonWriterState.Name);
+            }
+            CheckElementName(name);
+
+            _name = name;
+            _state = BsonWriterState.Value;
+        }
+
+        /// <summary>
+        /// Writes a BSON null to the writer.
+        /// </summary>
+        public abstract void WriteNull();
+
+        /// <summary>
+        /// Writes a BSON null element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteNull(string name)
+        {
+            WriteName(name);
+            WriteNull();
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the writer.
+        /// </summary>
+        /// <param name="objectId">The ObjectId.</param>
+        public abstract void WriteObjectId(ObjectId objectId);
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the writer.
+        /// </summary>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use WriteObjectId(ObjectId objectId) instead.")]
+        public void WriteObjectId(int timestamp, int machine, short pid, int increment)
+        {
+            var objectId = new ObjectId(timestamp, machine, pid, increment);
+            WriteObjectId(objectId);
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="objectId">The ObjectId.</param>
+        public void WriteObjectId(string name, ObjectId objectId)
+        {
+            WriteName(name);
+            WriteObjectId(objectId);
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="timestamp">The timestamp.</param>
+        /// <param name="machine">The machine hash.</param>
+        /// <param name="pid">The PID.</param>
+        /// <param name="increment">The increment.</param>
+        [Obsolete("Use WriteObjectId(string name, ObjectId objectId) instead.")]
+        public void WriteObjectId(string name, int timestamp, int machine, short pid, int increment)
+        {
+            WriteName(name);
+            WriteObjectId(timestamp, machine, pid, increment);
+        }
+
+        /// <summary>
+        /// Writes a raw BSON array.
+        /// </summary>
+        /// <param name="slice">The byte buffer containing the raw BSON array.</param>
+        public virtual void WriteRawBsonArray(IByteBuffer slice)
+        {
+            // overridden in BsonBinaryWriter
+
+            using (var bsonBuffer = new BsonBuffer())
+            {
+                BsonArray array;
+
+                // wrap the array in a fake document so we can deserialize it
+                var arrayLength = slice.Length;
+                var documentLength = arrayLength + 8;
+                bsonBuffer.WriteInt32(documentLength);
+                bsonBuffer.WriteByte((byte)BsonType.Array);
+                bsonBuffer.WriteByte((byte)'x');
+                bsonBuffer.WriteByte((byte)0);
+                bsonBuffer.ByteBuffer.WriteBytes(slice);
+                bsonBuffer.WriteByte((byte)0);
+
+                bsonBuffer.Position = 0;
+                using (var bsonReader = new BsonBinaryReader(bsonBuffer, true, BsonBinaryReaderSettings.Defaults))
+                {
+                    bsonReader.ReadStartDocument();
+                    bsonReader.ReadName("x");
+                    array = (BsonArray)BsonArraySerializer.Instance.Deserialize(bsonReader, typeof(BsonArray), null);
+                    bsonReader.ReadEndDocument();
+                }
+
+                BsonArraySerializer.Instance.Serialize(this, typeof(BsonArray), array, null);
+            }
+        }
+
+        /// <summary>
+        /// Writes a raw BSON array.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="slice">The byte buffer containing the raw BSON array.</param>
+        public void WriteRawBsonArray(string name, IByteBuffer slice)
+        {
+            WriteName(name);
+            WriteRawBsonArray(slice);
+        }
+
+        /// <summary>
+        /// Writes a raw BSON document.
+        /// </summary>
+        /// <param name="slice">The byte buffer containing the raw BSON document.</param>
+        public virtual void WriteRawBsonDocument(IByteBuffer slice)
+        {
+            // overridden in BsonBinaryWriter
+            using (var bsonReader = new BsonBinaryReader(new BsonBuffer(slice, false), true, BsonBinaryReaderSettings.Defaults))
+            {
+                var document = BsonSerializer.Deserialize<BsonDocument>(bsonReader);
+                BsonDocumentSerializer.Instance.Serialize(this, typeof(BsonDocument), document, null);
+            }
+        }
+
+        /// <summary>
+        /// Writes a raw BSON document.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="slice">The byte buffer containing the raw BSON document.</param>
+        public void WriteRawBsonDocument(string name, IByteBuffer slice)
+        {
+            WriteName(name);
+            WriteRawBsonDocument(slice);
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression to the writer.
+        /// </summary>
+        /// <param name="regex">A BsonRegularExpression.</param>
+        public abstract void WriteRegularExpression(BsonRegularExpression regex);
+
+        /// <summary>
+        /// Writes a BSON regular expression to the writer.
+        /// </summary>
+        /// <param name="pattern">A regular expression pattern.</param>
+        /// <param name="options">A regular expression options.</param>
+        [Obsolete("Use WriteRegularExpression(BsonRegularExpression regex) instead.")]
+        public void WriteRegularExpression(string pattern, string options)
+        {
+            var regex = new BsonRegularExpression(pattern, options);
+            WriteRegularExpression(regex);
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="regex">A BsonRegularExpression.</param>
+        public void WriteRegularExpression(string name, BsonRegularExpression regex)
+        {
+            WriteName(name);
+            WriteRegularExpression(regex);
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="pattern">A regular expression pattern.</param>
+        /// <param name="options">A regular expression options.</param>
+        [Obsolete("Use WriteRegularExpression(string name, BsonRegularExpression regex) instead.")]
+        public void WriteRegularExpression(string name, string pattern, string options)
+        {
+            WriteName(name);
+            WriteRegularExpression(pattern, options);
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON array to the writer.
+        /// </summary>
+        public virtual void WriteStartArray()
+        {
+            _serializationDepth++;
+            if (_serializationDepth > _settings.MaxSerializationDepth)
+            {
+                throw new BsonSerializationException("Maximum serialization depth exceeded (does the object being serialized have a circular reference?).");
+            }
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON array element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteStartArray(string name)
+        {
+            WriteName(name);
+            WriteStartArray();
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON document to the writer.
+        /// </summary>
+        public virtual void WriteStartDocument()
+        {
+            _serializationDepth++;
+            if (_serializationDepth > _settings.MaxSerializationDepth)
+            {
+                throw new BsonSerializationException("Maximum serialization depth exceeded (does the object being serialized have a circular reference?).");
+            }
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON document element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteStartDocument(string name)
+        {
+            WriteName(name);
+            WriteStartDocument();
+        }
+
+        /// <summary>
+        /// Writes a BSON String to the writer.
+        /// </summary>
+        /// <param name="value">The String value.</param>
+        public abstract void WriteString(string value);
+
+        /// <summary>
+        /// Writes a BSON String element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The String value.</param>
+        public void WriteString(string name, string value)
+        {
+            WriteName(name);
+            WriteString(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON Symbol to the writer.
+        /// </summary>
+        /// <param name="value">The symbol.</param>
+        public abstract void WriteSymbol(string value);
+
+        /// <summary>
+        /// Writes a BSON Symbol element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The symbol.</param>
+        public void WriteSymbol(string name, string value)
+        {
+            WriteName(name);
+            WriteSymbol(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON timestamp to the writer.
+        /// </summary>
+        /// <param name="value">The combined timestamp/increment value.</param>
+        public abstract void WriteTimestamp(long value);
+
+        /// <summary>
+        /// Writes a BSON timestamp element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        /// <param name="value">The combined timestamp/increment value.</param>
+        public void WriteTimestamp(string name, long value)
+        {
+            WriteName(name);
+            WriteTimestamp(value);
+        }
+
+        /// <summary>
+        /// Writes a BSON undefined to the writer.
+        /// </summary>
+        public abstract void WriteUndefined();
+
+        /// <summary>
+        /// Writes a BSON undefined element to the writer.
+        /// </summary>
+        /// <param name="name">The name of the element.</param>
+        public void WriteUndefined(string name)
+        {
+            WriteName(name);
+            WriteUndefined();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Checks that the element name is valid.
+        /// </summary>
+        /// <param name="name">The element name to be checked.</param>
+        protected void CheckElementName(string name)
+        {
+            if (_checkUpdateDocument)
+            {
+                _checkElementNames = name == "" || name[0] != '$';
+                _checkUpdateDocument = false;
+                return;
+            }
+
+            if (_checkElementNames)
+            {
+                if (name == "")
+                {
+                    var message = "Element name '' is not valid because it is an empty string.";
+                    throw new BsonSerializationException(message);
+                }
+
+                if (name[0] == '$')
+                {
+                    // a few element names starting with $ have to be allowed for historical reasons
+                    switch (name)
+                    {
+                        case "$code":
+                        case "$db":
+                        case "$id":
+                        case "$ref":
+                        case "$scope":
+                            break;
+                        default:
+                            var message = string.Format("Element name '{0}' is not valid because it starts with a '$'.", name);
+                            throw new BsonSerializationException(message);
+                    }
+                }
+
+                if (name.IndexOf('.') != -1)
+                {
+                    var message = string.Format("Element name '{0}' is not valid because it contains a '.'.", name);
+                    throw new BsonSerializationException(message);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Disposes of any resources used by the writer.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+        }
+
+        /// <summary>
+        /// Throws an InvalidOperationException when the method called is not valid for the current ContextType.
+        /// </summary>
+        /// <param name="methodName">The name of the method.</param>
+        /// <param name="actualContextType">The actual ContextType.</param>
+        /// <param name="validContextTypes">The valid ContextTypes.</param>
+        protected void ThrowInvalidContextType(
+            string methodName,
+            ContextType actualContextType,
+            params ContextType[] validContextTypes)
+        {
+            var validContextTypesString = string.Join(" or ", validContextTypes.Select(c => c.ToString()).ToArray());
+            var message = string.Format(
+                "{0} can only be called when ContextType is {1}, not when ContextType is {2}.",
+                methodName, validContextTypesString, actualContextType);
+            throw new InvalidOperationException(message);
+        }
+
+        /// <summary>
+        /// Throws an InvalidOperationException when the method called is not valid for the current state.
+        /// </summary>
+        /// <param name="methodName">The name of the method.</param>
+        /// <param name="validStates">The valid states.</param>
+        protected void ThrowInvalidState(string methodName, params BsonWriterState[] validStates)
+        {
+            string message;
+            if (_state == BsonWriterState.Initial || _state == BsonWriterState.ScopeDocument || _state == BsonWriterState.Done)
+            {
+                if (!methodName.StartsWith("End", StringComparison.Ordinal) && methodName != "WriteName")
+                {
+                    var typeName = methodName.Substring(5);
+                    if (typeName.StartsWith("Start", StringComparison.Ordinal))
+                    {
+                        typeName = typeName.Substring(5);
+                    }
+                    var article = "A";
+                    if (new char[] { 'A', 'E', 'I', 'O', 'U' }.Contains(typeName[0]))
+                    {
+                        article = "An";
+                    }
+                    message = string.Format(
+                        "{0} {1} value cannot be written to the root level of a BSON document.",
+                        article, typeName);
+                    throw new InvalidOperationException(message);
+                }
+            }
+
+            var validStatesString = string.Join(" or ", validStates.Select(s => s.ToString()).ToArray());
+            message = string.Format(
+                "{0} can only be called when State is {1}, not when State is {2}",
+                methodName, validStatesString, _state);
+            throw new InvalidOperationException(message);
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriter.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f48f8def7bac1224cb268bdaa9e7076b
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 135 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterSettings.cs

@@ -0,0 +1,135 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a BsonWriter.
+    /// </summary>
+    [Serializable]
+    public abstract class BsonWriterSettings
+    {
+        // private fields
+        private GuidRepresentation _guidRepresentation = BsonDefaults.GuidRepresentation;
+        private bool _isFrozen;
+        private int _maxSerializationDepth = BsonDefaults.MaxSerializationDepth;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the BsonWriterSettings class.
+        /// </summary>
+        protected BsonWriterSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the BsonWriterSettings class.
+        /// </summary>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        protected BsonWriterSettings(GuidRepresentation guidRepresentation)
+        {
+            _guidRepresentation = guidRepresentation;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets the representation for Guids.
+        /// </summary>
+        public GuidRepresentation GuidRepresentation
+        {
+            get { return _guidRepresentation; }
+            set
+            {
+                if (_isFrozen) { ThrowFrozenException(); }
+                _guidRepresentation = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets whether the settings are frozen.
+        /// </summary>
+        public bool IsFrozen
+        {
+            get { return _isFrozen; }
+        }
+
+        /// <summary>
+        /// Gets or sets the max serialization depth allowed (used to detect circular references).
+        /// </summary>
+        public int MaxSerializationDepth
+        {
+            get { return _maxSerializationDepth; }
+            set
+            {
+                if (_isFrozen) { ThrowFrozenException(); }
+                _maxSerializationDepth = value;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public BsonWriterSettings Clone()
+        {
+            return CloneImplementation();
+        }
+
+        /// <summary>
+        /// Freezes the settings.
+        /// </summary>
+        /// <returns>The frozen settings.</returns>
+        public BsonWriterSettings Freeze()
+        {
+            _isFrozen = true;
+            return this;
+        }
+
+        /// <summary>
+        /// Returns a frozen copy of the settings.
+        /// </summary>
+        /// <returns>A frozen copy of the settings.</returns>
+        public BsonWriterSettings FrozenCopy()
+        {
+            if (_isFrozen)
+            {
+                return this;
+            }
+            else
+            {
+                return Clone().Freeze();
+            }
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected abstract BsonWriterSettings CloneImplementation();
+
+        /// <summary>
+        /// Throws an InvalidOperationException when an attempt is made to change a setting after the settings are frozen.
+        /// </summary>
+        protected void ThrowFrozenException()
+        {
+            var message = string.Format("{0} is frozen.", this.GetType().Name);
+            throw new InvalidOperationException(message);
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a1fa0352ac847874a85adab82910f1ce
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 48 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterState.cs

@@ -0,0 +1,48 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents the state of a BsonWriter.
+    /// </summary>
+    public enum BsonWriterState
+    {
+        /// <summary>
+        /// The initial state.
+        /// </summary>
+        Initial,
+        /// <summary>
+        /// The writer is positioned to write a name.
+        /// </summary>
+        Name,
+        /// <summary>
+        /// The writer is positioned to write a value.
+        /// </summary>
+        Value,
+        /// <summary>
+        /// The writer is positioned to write a scope document (call WriteStartDocument to start writing the scope document).
+        /// </summary>
+        ScopeDocument,
+        /// <summary>
+        /// The writer is done.
+        /// </summary>
+        Done,
+        /// <summary>
+        /// The writer is closed.
+        /// </summary>
+        Closed
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/BsonWriterState.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 799d36ab68c96c24190477a99a42cbdf
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 538 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteArrayBuffer.cs

@@ -0,0 +1,538 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// A BSON buffer that is backed by a byte array.
+    /// </summary>
+    public class ByteArrayBuffer : IByteBuffer
+    {
+        // private fields
+        private bool _disposed;
+        private byte[] _bytes;
+        private int _sliceOffset;
+        private int _capacity;
+        private int _length;
+        private int _position;
+        private bool _isReadOnly;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ByteArrayBuffer"/> class.
+        /// </summary>
+        /// <param name="bytes">The backing bytes.</param>
+        /// <param name="sliceOffset">The offset where the slice begins.</param>
+        /// <param name="length">The length of the slice.</param>
+        /// <param name="isReadOnly">Whether the buffer is read only.</param>
+        /// <exception cref="System.ArgumentNullException">bytes</exception>
+        public ByteArrayBuffer(byte[] bytes, int sliceOffset, int length, bool isReadOnly)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+
+            _bytes = bytes;
+            _sliceOffset = sliceOffset;
+            _capacity = isReadOnly ? length : bytes.Length - _sliceOffset;
+            _length = length;
+            _isReadOnly = isReadOnly;
+            _position = 0;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets the capacity.
+        /// </summary>
+        /// <value>
+        /// The capacity.
+        /// </value>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.NotSupportedException">The capacity of a ByteArrayBuffer cannot be changed.</exception>
+        public int Capacity
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _capacity;
+            }
+            set
+            {
+                ThrowIfDisposed();
+                throw new NotSupportedException("The capacity of a ByteArrayBuffer cannot be changed.");
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is read only.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if this instance is read only; otherwise, <c>false</c>.
+        /// </value>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public bool IsReadOnly
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _isReadOnly;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the length.
+        /// </summary>
+        /// <value>
+        /// The length.
+        /// </value>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">The length of a read only buffer cannot be changed.</exception>
+        /// <exception cref="System.ArgumentOutOfRangeException">Length</exception>
+        public int Length
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _length;
+            }
+            set
+            {
+                ThrowIfDisposed();
+                EnsureIsWritable();
+                if (value < 0 || value > _capacity)
+                {
+                    throw new ArgumentOutOfRangeException("length");
+                }
+                _length = value;
+                if (_position > _length)
+                {
+                    _position = _length;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the position.
+        /// </summary>
+        /// <value>
+        /// The position.
+        /// </value>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.ArgumentOutOfRangeException">Position</exception>
+        public int Position
+        {
+            get
+            {
+                ThrowIfDisposed();
+                return _position;
+            }
+            set
+            {
+                ThrowIfDisposed();
+                if (value < 0 || value > _capacity)
+                {
+                    throw new ArgumentOutOfRangeException("Position");
+                }
+                _position = value;
+                if (_length < _position)
+                {
+                    _length = _position;
+                }
+            }
+        }
+
+        // protected properties
+        /// <summary>
+        /// Gets a value indicating whether this <see cref="ByteArrayBuffer"/> is disposed.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if disposed; otherwise, <c>false</c>.
+        /// </value>
+        protected bool Disposed
+        {
+            get { return _disposed; }
+        }
+
+        /// <summary>
+        /// Gets the slice offset.
+        /// </summary>
+        /// <value>
+        /// The slice offset.
+        /// </value>
+        protected int SliceOffset
+        {
+            get { return _sliceOffset; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Clears this instance.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">Write operations are not allowed for read only buffers.</exception>
+        public virtual void Clear()
+        {
+            ThrowIfDisposed();
+            EnsureIsWritable();
+            _position = 0;
+            _length = 0;
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Finds the next null byte.
+        /// </summary>
+        /// <returns>
+        /// The position of the next null byte.
+        /// </returns>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public int FindNullByte()
+        {
+            ThrowIfDisposed();
+            var index = Array.IndexOf<byte>(_bytes, 0, _sliceOffset + _position, _length - _position);
+            return (index == -1) ? -1 : index - _sliceOffset;
+        }
+
+        /// <summary>
+        /// Gets a slice of this buffer.
+        /// </summary>
+        /// <param name="position">The position of the start of the slice.</param>
+        /// <param name="length">The length of the slice.</param>
+        /// <returns>
+        /// A slice of this buffer.
+        /// </returns>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">GetSlice can only be called for read only buffers.</exception>
+        /// <exception cref="System.ArgumentOutOfRangeException">
+        /// position
+        /// or
+        /// length
+        /// </exception>
+        public virtual IByteBuffer GetSlice(int position, int length)
+        {
+            ThrowIfDisposed();
+            EnsureIsReadOnly();
+            if (position < 0 || position >= _length)
+            {
+                throw new ArgumentOutOfRangeException("position");
+            }
+            if (length <= 0 || length > _length - position)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+
+            return new ByteArrayBuffer(_bytes, _sliceOffset + position, length, true);
+        }
+
+        /// <summary>
+        /// Loads the buffer from a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="count">The count.</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">Write operations are not allowed for read only buffers.</exception>
+        /// <exception cref="System.ArgumentNullException">stream</exception>
+        /// <exception cref="System.ArgumentOutOfRangeException">count</exception>
+        public void LoadFrom(Stream stream, int count)
+        {
+            ThrowIfDisposed();
+            EnsureIsWritable();
+            if (stream == null)
+            {
+                throw new ArgumentNullException("stream");
+            }
+            if (count > _capacity - _position)
+            {
+                throw new ArgumentOutOfRangeException("count");
+            }
+
+            EnsureSpaceAvailable(count);
+            var position = _position; // don't advance position
+            while (count > 0)
+            {
+                var bytesRead = stream.Read(_bytes, _sliceOffset + position, count);
+                if (bytesRead == 0)
+                {
+                    throw new EndOfStreamException();
+                }
+                position += bytesRead;
+                count -= bytesRead;
+            }
+            if (_length < position)
+            {
+                _length = position;
+            }
+        }
+
+        /// <summary>
+        /// Makes this buffer read only.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public void MakeReadOnly()
+        {
+            ThrowIfDisposed();
+            _isReadOnly = true;
+        }
+
+        /// <summary>
+        /// Read directly from the backing bytes. The returned ArraySegment points directly to the backing bytes for
+        /// the current position and you can read the bytes directly from there. If the backing bytes happen to span
+        /// a chunk boundary shortly after the current position there might not be enough bytes left in the current
+        /// chunk in which case the returned ArraySegment will have a Count of zero and you should call ReadBytes instead.
+        /// 
+        /// When ReadBackingBytes returns the position will have been advanced by count bytes *if and only if* there
+        /// were count bytes left in the current chunk.
+        /// </summary>
+        /// <param name="count">The number of bytes you need to read.</param>
+        /// <returns>
+        /// An ArraySegment pointing directly to the backing bytes for the current position.
+        /// </returns>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public ArraySegment<byte> ReadBackingBytes(int count)
+        {
+            ThrowIfDisposed();
+            EnsureDataAvailable(count);
+            var offset = _sliceOffset + _position;
+            _position += count;
+            return new ArraySegment<byte>(_bytes, offset, count);
+        }
+
+        /// <summary>
+        /// Reads a byte.
+        /// </summary>
+        /// <returns>
+        /// A byte.
+        /// </returns>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public byte ReadByte()
+        {
+            ThrowIfDisposed();
+            EnsureDataAvailable(1);
+            return _bytes[_sliceOffset + _position++];
+        }
+
+        /// <summary>
+        /// Reads bytes.
+        /// </summary>
+        /// <param name="destination">The destination.</param>
+        /// <param name="destinationOffset">The destination offset.</param>
+        /// <param name="count">The count.</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public void ReadBytes(byte[] destination, int destinationOffset, int count)
+        {
+            ThrowIfDisposed();
+            EnsureDataAvailable(count);
+            Buffer.BlockCopy(_bytes, _sliceOffset + _position, destination, destinationOffset, count);
+            _position += count;
+        }
+
+        /// <summary>
+        /// Reads bytes.
+        /// </summary>
+        /// <param name="count">The count.</param>
+        /// <returns>
+        /// The bytes.
+        /// </returns>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public byte[] ReadBytes(int count)
+        {
+            ThrowIfDisposed();
+
+            var destination = new byte[count];
+            ReadBytes(destination, 0, count);
+
+            return destination;
+        }
+
+        /// <summary>
+        /// Write directly to the backing bytes. The returned ArraySegment points directly to the backing bytes for
+        /// the current position and you can write the bytes directly to there. If the backing bytes happen to span
+        /// a chunk boundary shortly after the current position there might not be enough bytes left in the current
+        /// chunk in which case the returned ArraySegment will have a Count of zero and you should call WriteBytes instead.
+        /// 
+        /// When WriteBackingBytes returns the position has not been advanced. After you have written up to count
+        /// bytes directly to the backing bytes advance the position by the number of bytes actually written.
+        /// </summary>
+        /// <param name="count">The count.</param>
+        /// <returns>
+        /// An ArraySegment pointing directly to the backing bytes for the current position.
+        /// </returns>
+        public ArraySegment<byte> WriteBackingBytes(int count)
+        {
+            ThrowIfDisposed();
+            EnsureSpaceAvailable(count);
+            var offset = _sliceOffset + _position;
+            return new ArraySegment<byte>(_bytes, offset, count);
+        }
+
+        /// <summary>
+        /// Writes a byte.
+        /// </summary>
+        /// <param name="source">The byte.</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">Write operations are not allowed for read only buffers.</exception>
+        public void WriteByte(byte source)
+        {
+            ThrowIfDisposed();
+            EnsureIsWritable();
+            EnsureSpaceAvailable(1);
+            _bytes[_sliceOffset + _position++] = source;
+            if (_length < _position)
+            {
+                _length = _position;
+            }
+        }
+
+        /// <summary>
+        /// Writes bytes.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">Write operations are not allowed for read only buffers.</exception>
+        public void WriteBytes(byte[] bytes)
+        {
+            ThrowIfDisposed();
+            EnsureIsWritable();
+            var count = bytes.Length;
+            EnsureSpaceAvailable(count);
+            Buffer.BlockCopy(bytes, 0, _bytes, _sliceOffset + _position, count);
+            _position += count;
+            if (_length < _position)
+            {
+                _length = _position;
+            }
+        }
+
+        /// <summary>
+        /// Writes bytes.
+        /// </summary>
+        /// <param name="source">The bytes (in the form of an IByteBuffer).</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        /// <exception cref="System.InvalidOperationException">Write operations are not allowed for read only buffers.</exception>
+        public void WriteBytes(IByteBuffer source)
+        {
+            ThrowIfDisposed();
+            EnsureIsWritable();
+            var count = source.Length;
+            EnsureSpaceAvailable(count);
+            var savedPosition = source.Position;
+            source.Position = 0;
+            source.ReadBytes(_bytes, _sliceOffset + _position, count);
+            _position += count;
+            if (_length < _position)
+            {
+                _length = _position;
+            }
+            source.Position = savedPosition;
+        }
+
+        /// <summary>
+        /// Writes Length bytes from this buffer starting at Position 0 to a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer</exception>
+        public void WriteTo(Stream stream)
+        {
+            ThrowIfDisposed();
+            stream.Write(_bytes, _sliceOffset, _length);
+        }
+
+        // protected methods
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            // subclasses override this method if they have anything to Dispose
+            _disposed = true;
+        }
+
+        /// <summary>
+        /// Ensures the buffer is writable.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer is not writable.</exception>
+        protected void EnsureIsWritable()
+        {
+            if (_isReadOnly)
+            {
+                var message = string.Format("{0} is not writable.", GetType().Name);
+                throw new InvalidOperationException(message);
+            }
+        }
+
+        /// <summary>
+        /// Ensures the buffer is read only.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException">ByteArrayBuffer is not read only.</exception>
+        protected void EnsureIsReadOnly()
+        {
+            if (!_isReadOnly)
+            {
+                var message = string.Format("{0} is not read only.", GetType().Name);
+                throw new InvalidOperationException(message);
+            }
+        }
+
+        /// <summary>
+        /// Throws if disposed.
+        /// </summary>
+        /// <exception cref="System.ObjectDisposedException"></exception>
+        protected void ThrowIfDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().Name);
+            }
+        }
+
+        // private methods
+        private void EnsureDataAvailable(int needed)
+        {
+            if (needed > _length - _position)
+            {
+                var available = _length - _position;
+                var message = string.Format(
+                    "Not enough input bytes available. Needed {0}, but only {1} are available (at position {2}).",
+                    needed, available, _position);
+                throw new EndOfStreamException(message);
+            }
+        }
+
+        private void EnsureSpaceAvailable(int needed)
+        {
+            if (needed > _capacity - _length)
+            {
+                var available = _capacity - _length;
+                var message = string.Format(
+                    "Not enough space available. Needed {0}, but only {1} are available (at position {2}).",
+                    needed, available, _position);
+                throw new EndOfStreamException(message);
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteArrayBuffer.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dbe492da2e91b8441a2083a7deb18747
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 98 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteBufferFactory.cs

@@ -0,0 +1,98 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a factory for IBsonBuffers.
+    /// </summary>
+    public static class ByteBufferFactory
+    {
+        /// <summary>
+        /// Creates a buffer of the specified fixed capacity. Depending on the required capacity, either a SingleChunkBuffer or a MultiChunkBuffer will be created.
+        /// </summary>
+        /// <param name="chunkPool">The chunk pool.</param>
+        /// <param name="fixedCapacity">The required capacity.</param>
+        /// <returns>A buffer.</returns>
+        public static IByteBuffer Create(BsonChunkPool chunkPool, int fixedCapacity)
+        {
+            if (chunkPool == null)
+            {
+                throw new ArgumentNullException("pool");
+            }
+            if (fixedCapacity <= 0)
+            {
+                throw new ArgumentOutOfRangeException("capacity");
+            }
+
+            if (fixedCapacity < chunkPool.ChunkSize)
+            {
+                var chunk = chunkPool.AcquireChunk();
+                return new SingleChunkBuffer(chunk, 0, 0, false);
+            }
+            else
+            {
+                var chunksNeeded = ((fixedCapacity - 1) / chunkPool.ChunkSize) + 1;
+                var chunks = new List<BsonChunk>(chunksNeeded);
+                for (int i = 0; i < chunksNeeded; i++)
+                {
+                    chunks.Add(chunkPool.AcquireChunk());
+                }
+                return new MultiChunkBuffer(chunks, 0, 0, false);
+            }
+        }
+
+        /// <summary>
+        /// Loads a byte buffer from a stream (the first 4 bytes in the stream are the length of the data).
+        /// Depending on the required capacity, either a SingleChunkBuffer or a MultiChunkBuffer will be created.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <returns>A buffer.</returns>
+        /// <exception cref="System.ArgumentNullException">stream</exception>
+        public static IByteBuffer LoadFrom(Stream stream)
+        {
+            if (stream == null)
+            {
+                throw new ArgumentNullException("stream");
+            }
+
+            var lengthBytes = new byte[4];
+            var offset = 0;
+            var count = 4;
+            while (count > 0)
+            {
+                var bytesRead = stream.Read(lengthBytes, offset, count);
+                if (bytesRead == 0)
+                {
+                    throw new EndOfStreamException();
+                }
+                offset += bytesRead;
+                count -= bytesRead;
+            }
+            var length = BitConverter.ToInt32(lengthBytes, 0);
+
+            var buffer = Create(BsonChunkPool.Default, length);
+            buffer.WriteBytes(lengthBytes);
+            buffer.LoadFrom(stream, length - 4);
+            buffer.Position = 0;
+
+            return buffer;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ByteBufferFactory.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2996822bc562c40488506180d5e015fe
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 44 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ContextType.cs

@@ -0,0 +1,44 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Used by BsonReaders and BsonWriters to represent the current context.
+    /// </summary>
+    public enum ContextType
+    {
+        /// <summary>
+        /// The top level of a BSON document.
+        /// </summary>
+        TopLevel,
+        /// <summary>
+        /// A (possibly embedded) BSON document.
+        /// </summary>
+        Document,
+        /// <summary>
+        /// A BSON array.
+        /// </summary>
+        Array,
+        /// <summary>
+        /// A JavaScriptWithScope BSON value.
+        /// </summary>
+        JavaScriptWithScope,
+        /// <summary>
+        /// The scope document of a JavaScriptWithScope BSON value.
+        /// </summary>
+        ScopeDocument
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/ContextType.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 9c0cce13501704c4cad24f554835b647
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 162 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/IByteBuffer.cs

@@ -0,0 +1,162 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a byte buffer (backed by various means depending on the implementation).
+    /// </summary>
+    public interface IByteBuffer : IDisposable
+    {
+        // properties
+        /// <summary>
+        /// Gets or sets the capacity.
+        /// </summary>
+        /// <value>
+        /// The capacity.
+        /// </value>
+        int Capacity { get; set; }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is read only.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if this instance is read only; otherwise, <c>false</c>.
+        /// </value>
+        bool IsReadOnly { get; }
+
+        /// <summary>
+        /// Gets or sets the length.
+        /// </summary>
+        /// <value>
+        /// The length.
+        /// </value>
+        int Length { get; set; }
+
+        /// <summary>
+        /// Gets or sets the position.
+        /// </summary>
+        /// <value>
+        /// The position.
+        /// </value>
+        int Position { get; set; }
+
+        // methods
+        /// <summary>
+        /// Clears this instance.
+        /// </summary>
+        void Clear();
+
+        /// <summary>
+        /// Finds the next null byte.
+        /// </summary>
+        /// <returns>The position of the next null byte.</returns>
+        int FindNullByte();
+
+        /// <summary>
+        /// Gets a slice of this buffer.
+        /// </summary>
+        /// <param name="position">The position of the start of the slice.</param>
+        /// <param name="length">The length of the slice.</param>
+        /// <returns>A slice of this buffer.</returns>
+        IByteBuffer GetSlice(int position, int length);
+
+        /// <summary>
+        /// Loads the buffer from a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="count">The count.</param>
+        void LoadFrom(Stream stream, int count);
+
+        /// <summary>
+        /// Makes this buffer read only.
+        /// </summary>
+        void MakeReadOnly();
+
+        /// <summary>
+        /// Read directly from the backing bytes. The returned ArraySegment points directly to the backing bytes for
+        /// the current position and you can read the bytes directly from there. If the backing bytes happen to span
+        /// a chunk boundary shortly after the current position there might not be enough bytes left in the current
+        /// chunk in which case the returned ArraySegment will have a Count of zero and you should call ReadBytes instead.
+        /// 
+        /// When ReadBackingBytes returns the position will have been advanced by count bytes *if and only if* there
+        /// were count bytes left in the current chunk.
+        /// </summary>
+        /// <param name="count">The number of bytes you need to read.</param>
+        /// <returns>An ArraySegment pointing directly to the backing bytes for the current position.</returns>
+        ArraySegment<byte> ReadBackingBytes(int count);
+
+        /// <summary>
+        /// Reads a byte.
+        /// </summary>
+        /// <returns>A byte.</returns>
+        byte ReadByte();
+
+        /// <summary>
+        /// Reads bytes.
+        /// </summary>
+        /// <param name="destination">The destination.</param>
+        /// <param name="destinationOffset">The destination offset.</param>
+        /// <param name="count">The count.</param>
+        void ReadBytes(byte[] destination, int destinationOffset, int count);
+
+        /// <summary>
+        /// Reads bytes.
+        /// </summary>
+        /// <param name="count">The count.</param>
+        /// <returns>The bytes.</returns>
+        byte[] ReadBytes(int count);
+
+        /// <summary>
+        /// Write directly to the backing bytes. The returned ArraySegment points directly to the backing bytes for
+        /// the current position and you can write the bytes directly to there. If the backing bytes happen to span
+        /// a chunk boundary shortly after the current position there might not be enough bytes left in the current
+        /// chunk in which case the returned ArraySegment will have a Count of zero and you should call WriteBytes instead.
+        /// 
+        /// When WriteBackingBytes returns the position has not been advanced. After you have written up to count
+        /// bytes directly to the backing bytes advance the position by the number of bytes actually written.
+        /// </summary>
+        /// <param name="count">The count.</param>
+        /// <returns>An ArraySegment pointing directly to the backing bytes for the current position.</returns>
+        ArraySegment<byte> WriteBackingBytes(int count);
+        
+        /// <summary>
+        /// Writes a byte.
+        /// </summary>
+        /// <param name="source">The byte.</param>
+        void WriteByte(byte source);
+
+        /// <summary>
+        /// Writes bytes.
+        /// </summary>
+        /// <param name="source">The bytes (in the form of a byte array).</param>
+        void WriteBytes(byte[] source);
+
+        /// <summary>
+        /// Writes bytes.
+        /// </summary>
+        /// <param name="source">The bytes (in the form of an IByteBuffer).</param>
+        void WriteBytes(IByteBuffer source);
+
+        /// <summary>
+        /// Writes Length bytes from this buffer starting at Position 0 to a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        void WriteTo(Stream stream);
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/IByteBuffer.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a5126352ea4a3a8419b35ff9fcab6f00
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 99 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonBuffer.cs

@@ -0,0 +1,99 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// This class represents a JSON string buffer.
+    /// </summary>
+    public class JsonBuffer
+    {
+        // private fields
+        private string _buffer;
+        private int _position;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the JsonBuffer class.
+        /// </summary>
+        /// <param name="buffer">The string.</param>
+        public JsonBuffer(string buffer)
+        {
+            _buffer = buffer;
+            _position = 0;
+        }
+
+        // internal properties
+        /// <summary>
+        /// Gets the length of the JSON string.
+        /// </summary>
+        public int Length
+        {
+            get { return _buffer.Length; }
+        }
+
+        /// <summary>
+        /// Gets or sets the current position.
+        /// </summary>
+        public int Position
+        {
+            get { return _position; }
+            set { _position = value; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Reads a character from the buffer.
+        /// </summary>
+        /// <returns>The next character (or -1 if at the end of the buffer).</returns>
+        public int Read()
+        {
+            return (_position >= _buffer.Length) ? -1 : _buffer[_position++];
+        }
+
+        /// <summary>
+        /// Reads a substring from the buffer.
+        /// </summary>
+        /// <param name="start">The zero based index of the start of the substring.</param>
+        /// <returns>The substring.</returns>
+        public string Substring(int start)
+        {
+            return _buffer.Substring(start);
+        }
+
+        /// <summary>
+        /// Reads a substring from the buffer.
+        /// </summary>
+        /// <param name="start">The zero based index of the start of the substring.</param>
+        /// <param name="count">The number of characters in the substring.</param>
+        /// <returns>The substring.</returns>
+        public string Substring(int start, int count)
+        {
+            return _buffer.Substring(start, count);
+        }
+
+        /// <summary>
+        /// Returns one character to the buffer (if the character matches the one at the current position the current position is moved back by one).
+        /// </summary>
+        /// <param name="c">The character to return.</param>
+        public void UnRead(int c)
+        {
+            if (c != -1 && _buffer[_position - 1] == c)
+            {
+                _position -= 1;
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonBuffer.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6473d471d01406f4397381b8a75ea02a
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 47 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonOutputMode.cs

@@ -0,0 +1,47 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents the output mode of a JsonWriter.
+    /// </summary>
+    public enum JsonOutputMode
+    {
+        /// <summary>
+        /// Output strict JSON.
+        /// </summary>
+        Strict,
+
+        /// <summary>
+        /// Use a format that can be pasted in to the MongoDB shell.
+        /// </summary>
+        Shell,
+
+        /// <summary>
+        /// Use JavaScript data types for some values.
+        /// </summary>
+        [Obsolete("Use Shell instead.")]
+        JavaScript = Shell,
+
+        /// <summary>
+        /// Use JavaScript and MongoDB data types for some values.
+        /// </summary>
+        [Obsolete("Use Shell instead.")]
+        TenGen = Shell
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonOutputMode.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fde14b24a0f8f9b47bd8f603e5e59940
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 1643 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReader.cs

@@ -0,0 +1,1643 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON reader for a JSON string.
+    /// </summary>
+    public class JsonReader : BsonReader
+    {
+        // private fields
+        private JsonBuffer _buffer;
+        private JsonReaderSettings _jsonReaderSettings; // same value as in base class just declared as derived class
+        private JsonReaderContext _context;
+        private JsonToken _currentToken;
+        private BsonValue _currentValue;
+        private JsonToken _pushedToken;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the JsonReader class.
+        /// </summary>
+        /// <param name="buffer">The buffer.</param>
+        /// <param name="settings">The reader settings.</param>
+        public JsonReader(JsonBuffer buffer, JsonReaderSettings settings)
+            : base(settings)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+
+            _buffer = buffer;
+            _jsonReaderSettings = settings; // already frozen by base class
+            _context = new JsonReaderContext(null, ContextType.TopLevel);
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the reader.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonReaderState.Closed)
+            {
+                State = BsonReaderState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Gets a bookmark to the reader's current position and state.
+        /// </summary>
+        /// <returns>A bookmark.</returns>
+        public override BsonReaderBookmark GetBookmark()
+        {
+            return new JsonReaderBookmark(State, CurrentBsonType, CurrentName, _context, _currentToken, _currentValue, _pushedToken, _buffer.Position);
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A BsonBinaryData.</returns>
+        public override BsonBinaryData ReadBinaryData()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBinaryData", BsonType.Binary);
+            State = GetNextState();
+            return _currentValue.AsBsonBinaryData;
+        }
+
+        /// <summary>
+        /// Reads a BSON boolean from the reader.
+        /// </summary>
+        /// <returns>A Boolean.</returns>
+        public override bool ReadBoolean()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadBoolean", BsonType.Boolean);
+            State = GetNextState();
+            return _currentValue.AsBoolean;
+        }
+
+        /// <summary>
+        /// Reads a BsonType from the reader.
+        /// </summary>
+        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
+        /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
+        /// <param name="found">Set to true if a matching value was found in the trie.</param>
+        /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
+        /// <returns>A BsonType.</returns>
+        public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            found = false;
+            value = default(TValue);
+            if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument)
+            {
+                // in JSON the top level value can be of any type so fall through
+                State = BsonReaderState.Type;
+            }
+            if (State != BsonReaderState.Type)
+            {
+                ThrowInvalidState("ReadBsonType", BsonReaderState.Type);
+            }
+
+            if (_context.ContextType == ContextType.Document)
+            {
+                var nameToken = PopToken();
+                switch (nameToken.Type)
+                {
+                    case JsonTokenType.String:
+                    case JsonTokenType.UnquotedString:
+                        if (bsonTrie != null)
+                        {
+                            found = bsonTrie.TryGetValue(nameToken.StringValue, out value);
+                        }
+                        CurrentName = nameToken.StringValue;
+                        break;
+                    case JsonTokenType.EndObject:
+                        State = BsonReaderState.EndOfDocument;
+                        return BsonType.EndOfDocument;
+                    default:
+                        var message = string.Format("JSON reader was expecting a name but found '{0}'.", nameToken.Lexeme);
+                        throw new Exception(message);
+                }
+
+                var colonToken = PopToken();
+                if (colonToken.Type != JsonTokenType.Colon)
+                {
+                    var message = string.Format("JSON reader was expecting ':' but found '{0}'.", colonToken.Lexeme);
+                    throw new Exception(message);
+                }
+            }
+
+            var valueToken = PopToken();
+            if (_context.ContextType == ContextType.Array && valueToken.Type == JsonTokenType.EndArray)
+            {
+                State = BsonReaderState.EndOfArray;
+                return BsonType.EndOfDocument;
+            }
+
+            var noValueFound = false;
+            switch (valueToken.Type)
+            {
+                case JsonTokenType.BeginArray:
+                    CurrentBsonType = BsonType.Array;
+                    break;
+                case JsonTokenType.BeginObject:
+                    CurrentBsonType = ParseExtendedJson();
+                    break;
+                case JsonTokenType.DateTime:
+                    CurrentBsonType = BsonType.DateTime;
+                    _currentValue = valueToken.DateTimeValue;
+                    break;
+                case JsonTokenType.Double:
+                    CurrentBsonType = BsonType.Double;
+                    _currentValue = valueToken.DoubleValue;
+                    break;
+                case JsonTokenType.EndOfFile:
+                    CurrentBsonType = BsonType.EndOfDocument;
+                    break;
+                case JsonTokenType.Int32:
+                    CurrentBsonType = BsonType.Int32;
+                    _currentValue = valueToken.Int32Value;
+                    break;
+                case JsonTokenType.Int64:
+                    CurrentBsonType = BsonType.Int64;
+                    _currentValue = valueToken.Int64Value;
+                    break;
+                case JsonTokenType.ObjectId:
+                    CurrentBsonType = BsonType.ObjectId;
+                    _currentValue = valueToken.ObjectIdValue;
+                    break;
+                case JsonTokenType.RegularExpression:
+                    CurrentBsonType = BsonType.RegularExpression;
+                    _currentValue = valueToken.RegularExpressionValue;
+                    break;
+                case JsonTokenType.String:
+                    CurrentBsonType = BsonType.String;
+                    _currentValue = valueToken.StringValue;
+                    break;
+                case JsonTokenType.UnquotedString:
+                    switch (valueToken.Lexeme)
+                    {
+                        case "false":
+                        case "true":
+                            CurrentBsonType = BsonType.Boolean;
+                            _currentValue = XmlConvert.ToBoolean(valueToken.Lexeme);
+                            break;
+                        case "Infinity":
+                            CurrentBsonType = BsonType.Double;
+                            _currentValue = double.PositiveInfinity;
+                            break;
+                        case "NaN":
+                            CurrentBsonType = BsonType.Double;
+                            _currentValue = double.NaN;
+                            break;
+                        case "null":
+                            CurrentBsonType = BsonType.Null;
+                            break;
+                        case "undefined":
+                            CurrentBsonType = BsonType.Undefined;
+                            break;
+                        case "BinData":
+                            CurrentBsonType = BsonType.Binary;
+                            _currentValue = ParseBinDataConstructor();
+                            break;
+                        case "Date":
+                            CurrentBsonType = BsonType.String;
+                            _currentValue = ParseDateTimeConstructor(false); // withNew = false
+                            break;
+                        case "HexData":
+                            CurrentBsonType = BsonType.Binary;
+                            _currentValue = ParseHexDataConstructor();
+                            break;
+                        case "ISODate":
+                            CurrentBsonType = BsonType.DateTime;
+                            _currentValue = ParseISODateTimeConstructor();
+                            break;
+                        case "MaxKey":
+                            CurrentBsonType = BsonType.MaxKey;
+                            _currentValue = BsonMaxKey.Value;
+                            break;
+                        case "MinKey":
+                            CurrentBsonType = BsonType.MinKey;
+                            _currentValue = BsonMinKey.Value;
+                            break;
+                        case "Number":
+                        case "NumberInt":
+                            CurrentBsonType = BsonType.Int32;
+                            _currentValue = ParseNumberConstructor();
+                            break;
+                        case "NumberLong":
+                            CurrentBsonType = BsonType.Int64;
+                            _currentValue = ParseNumberLongConstructor();
+                            break;
+                        case "ObjectId":
+                            CurrentBsonType = BsonType.ObjectId;
+                            _currentValue = ParseObjectIdConstructor();
+                            break;
+                        case "RegExp":
+                            CurrentBsonType = BsonType.RegularExpression;
+                            _currentValue = ParseRegularExpressionConstructor();
+                            break;
+                        case "Timestamp":
+                            CurrentBsonType = BsonType.Timestamp;
+                            _currentValue = ParseTimestampConstructor();
+                            break;
+                        case "UUID":
+                        case "GUID":
+                        case "CSUUID":
+                        case "CSGUID":
+                        case "JUUID":
+                        case "JGUID":
+                        case "PYUUID":
+                        case "PYGUID":
+                            CurrentBsonType = BsonType.Binary;
+                            _currentValue = ParseUUIDConstructor(valueToken.Lexeme);
+                            break;
+                        case "new":
+                            CurrentBsonType = ParseNew(out _currentValue);
+                            break;
+                        default:
+                            noValueFound = true;
+                            break;
+                    }
+                    break;
+                default:
+                    noValueFound = true;
+                    break;
+            }
+            if (noValueFound)
+            {
+                var message = string.Format("JSON reader was expecting a value but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            _currentToken = valueToken;
+
+            if (_context.ContextType == ContextType.Array || _context.ContextType == ContextType.Document)
+            {
+                var commaToken = PopToken();
+                if (commaToken.Type != JsonTokenType.Comma)
+                {
+                    PushToken(commaToken);
+                }
+            }
+
+            switch (_context.ContextType)
+            {
+                case ContextType.Document:
+                case ContextType.ScopeDocument:
+                default:
+                    State = BsonReaderState.Name;
+                    break;
+                case ContextType.Array:
+                case ContextType.JavaScriptWithScope:
+                case ContextType.TopLevel:
+                    State = BsonReaderState.Value;
+                    break;
+            }
+            return CurrentBsonType;
+        }
+
+        /// <summary>
+        /// Reads BSON binary data from the reader.
+        /// </summary>
+        /// <returns>A byte array.</returns>
+        public override byte[] ReadBytes()
+        {
+#pragma warning disable 618
+            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 {2}.", subType);
+                throw new Exception(message);
+            }
+
+            return binaryData.Bytes;
+#pragma warning restore
+        }
+
+        /// <summary>
+        /// Reads a BSON DateTime from the reader.
+        /// </summary>
+        /// <returns>The number of milliseconds since the Unix epoch.</returns>
+        public override long ReadDateTime()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDateTime", BsonType.DateTime);
+            State = GetNextState();
+            return _currentValue.AsBsonDateTime.MillisecondsSinceEpoch;
+        }
+
+        /// <summary>
+        /// Reads a BSON Double from the reader.
+        /// </summary>
+        /// <returns>A Double.</returns>
+        public override double ReadDouble()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadDouble", BsonType.Double);
+            State = GetNextState();
+            return _currentValue.AsDouble;
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON array from the reader.
+        /// </summary>
+        public override void ReadEndArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Array)
+            {
+                ThrowInvalidContextType("ReadEndArray", _context.ContextType, ContextType.Array);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfArray if at end of array
+            }
+            if (State != BsonReaderState.EndOfArray)
+            {
+                ThrowInvalidState("ReadEndArray", BsonReaderState.EndOfArray);
+            }
+
+            _context = _context.PopContext();
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType.");
+            }
+
+            if (_context.ContextType == ContextType.Array || _context.ContextType == ContextType.Document)
+            {
+                var commaToken = PopToken();
+                if (commaToken.Type != JsonTokenType.Comma)
+                {
+                    PushToken(commaToken);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Reads the end of a BSON document from the reader.
+        /// </summary>
+        public override void ReadEndDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
+            {
+                ThrowInvalidContextType("ReadEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
+            }
+            if (State == BsonReaderState.Type)
+            {
+                ReadBsonType(); // will set state to EndOfDocument if at end of document
+            }
+            if (State != BsonReaderState.EndOfDocument)
+            {
+                ThrowInvalidState("ReadEndDocument", BsonReaderState.EndOfDocument);
+            }
+
+            _context = _context.PopContext();
+            if (_context != null && _context.ContextType == ContextType.JavaScriptWithScope)
+            {
+                _context = _context.PopContext(); // JavaScriptWithScope
+                VerifyToken("}"); // outermost closing bracket for JavaScriptWithScope
+            }
+            switch (_context.ContextType)
+            {
+                case ContextType.Array: State = BsonReaderState.Type; break;
+                case ContextType.Document: State = BsonReaderState.Type; break;
+                case ContextType.TopLevel: State = BsonReaderState.Done; break;
+                default: throw new BsonInternalException("Unexpected ContextType");
+            }
+
+            if (_context.ContextType == ContextType.Array || _context.ContextType == ContextType.Document)
+            {
+                var commaToken = PopToken();
+                if (commaToken.Type != JsonTokenType.Comma)
+                {
+                    PushToken(commaToken);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Reads a BSON Int32 from the reader.
+        /// </summary>
+        /// <returns>An Int32.</returns>
+        public override int ReadInt32()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt32", BsonType.Int32);
+            State = GetNextState();
+            return _currentValue.AsInt32;
+        }
+
+        /// <summary>
+        /// Reads a BSON Int64 from the reader.
+        /// </summary>
+        /// <returns>An Int64.</returns>
+        public override long ReadInt64()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadInt64", BsonType.Int64);
+            State = GetNextState();
+            return _currentValue.AsInt64;
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScript()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScript", BsonType.JavaScript);
+            State = GetNextState();
+            return _currentValue.AsString;
+        }
+
+        /// <summary>
+        /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadJavaScriptWithScope()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadJavaScriptWithScope", BsonType.JavaScriptWithScope);
+            _context = new JsonReaderContext(_context, ContextType.JavaScriptWithScope);
+            State = BsonReaderState.ScopeDocument;
+            return _currentValue.AsString;
+        }
+
+        /// <summary>
+        /// Reads a BSON MaxKey from the reader.
+        /// </summary>
+        public override void ReadMaxKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMaxKey", BsonType.MaxKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON MinKey from the reader.
+        /// </summary>
+        public override void ReadMinKey()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadMinKey", BsonType.MinKey);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON null from the reader.
+        /// </summary>
+        public override void ReadNull()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadNull", BsonType.Null);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Reads a BSON ObjectId from the reader.
+        /// </summary>
+        /// <returns>An ObjectId.</returns>
+        public override ObjectId ReadObjectId()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadObjectId", BsonType.ObjectId);
+            State = GetNextState();
+            return _currentValue.AsObjectId;
+        }
+
+        /// <summary>
+        /// Reads a BSON regular expression from the reader.
+        /// </summary>
+        /// <returns>A BsonRegularExpression.</returns>
+        public override BsonRegularExpression ReadRegularExpression()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadRegularExpression", BsonType.RegularExpression);
+            State = GetNextState();
+            return _currentValue.AsBsonRegularExpression;
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON array.
+        /// </summary>
+        public override void ReadStartArray()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartArray", BsonType.Array);
+
+            _context = new JsonReaderContext(_context, ContextType.Array);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads the start of a BSON document.
+        /// </summary>
+        public override void ReadStartDocument()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadStartDocument", BsonType.Document);
+
+            _context = new JsonReaderContext(_context, ContextType.Document);
+            State = BsonReaderState.Type;
+        }
+
+        /// <summary>
+        /// Reads a BSON string from the reader.
+        /// </summary>
+        /// <returns>A String.</returns>
+        public override string ReadString()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadString", BsonType.String);
+            State = GetNextState();
+            return _currentValue.AsString;
+        }
+
+        /// <summary>
+        /// Reads a BSON symbol from the reader.
+        /// </summary>
+        /// <returns>A string.</returns>
+        public override string ReadSymbol()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadSymbol", BsonType.Symbol);
+            State = GetNextState();
+            return _currentValue.AsString;
+        }
+
+        /// <summary>
+        /// Reads a BSON timestamp from the reader.
+        /// </summary>
+        /// <returns>The combined timestamp/increment.</returns>
+        public override long ReadTimestamp()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadTimestamp", BsonType.Timestamp);
+            State = GetNextState();
+            var timestamp = _currentValue.AsBsonTimestamp;
+            return timestamp.Value;
+        }
+
+        /// <summary>
+        /// Reads a BSON undefined from the reader.
+        /// </summary>
+        public override void ReadUndefined()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            VerifyBsonType("ReadUndefined", BsonType.Undefined);
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Returns the reader to previously bookmarked position and state.
+        /// </summary>
+        /// <param name="bookmark">The bookmark.</param>
+        public override void ReturnToBookmark(BsonReaderBookmark bookmark)
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            var jsonReaderBookmark = (JsonReaderBookmark)bookmark;
+            State = jsonReaderBookmark.State;
+            CurrentBsonType = jsonReaderBookmark.CurrentBsonType;
+            CurrentName = jsonReaderBookmark.CurrentName;
+            _context = jsonReaderBookmark.CloneContext();
+            _currentToken = jsonReaderBookmark.CurrentToken;
+            _currentValue = jsonReaderBookmark.CurrentValue;
+            _pushedToken = jsonReaderBookmark.PushedToken;
+            _buffer.Position = jsonReaderBookmark.Position;
+        }
+
+        /// <summary>
+        /// Skips the name (reader must be positioned on a name).
+        /// </summary>
+        public override void SkipName()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Name)
+            {
+                ThrowInvalidState("SkipName", BsonReaderState.Name);
+            }
+
+            State = BsonReaderState.Value;
+        }
+
+        /// <summary>
+        /// Skips the value (reader must be positioned on a value).
+        /// </summary>
+        public override void SkipValue()
+        {
+            if (Disposed) { ThrowObjectDisposedException(); }
+            if (State != BsonReaderState.Value)
+            {
+                ThrowInvalidState("SkipValue", BsonReaderState.Value);
+            }
+
+            switch (CurrentBsonType)
+            {
+                case BsonType.Array:
+                    ReadStartArray();
+                    while (ReadBsonType() != BsonType.EndOfDocument)
+                    {
+                        SkipValue();
+                    }
+                    ReadEndArray();
+                    break;
+                case BsonType.Binary:
+                    ReadBinaryData();
+                    break;
+                case BsonType.Boolean:
+                    ReadBoolean();
+                    break;
+                case BsonType.DateTime:
+                    ReadDateTime();
+                    break;
+                case BsonType.Document:
+                    ReadStartDocument();
+                    while (ReadBsonType() != BsonType.EndOfDocument)
+                    {
+                        SkipName();
+                        SkipValue();
+                    }
+                    ReadEndDocument();
+                    break;
+                case BsonType.Double:
+                    ReadDouble();
+                    break;
+                case BsonType.Int32:
+                    ReadInt32();
+                    break;
+                case BsonType.Int64:
+                    ReadInt64();
+                    break;
+                case BsonType.JavaScript:
+                    ReadJavaScript();
+                    break;
+                case BsonType.JavaScriptWithScope:
+                    ReadJavaScriptWithScope();
+                    ReadStartDocument();
+                    while (ReadBsonType() != BsonType.EndOfDocument)
+                    {
+                        SkipName();
+                        SkipValue();
+                    }
+                    ReadEndDocument();
+                    break;
+                case BsonType.MaxKey:
+                    ReadMaxKey();
+                    break;
+                case BsonType.MinKey:
+                    ReadMinKey();
+                    break;
+                case BsonType.Null:
+                    ReadNull();
+                    break;
+                case BsonType.ObjectId:
+                    ReadObjectId();
+                    break;
+                case BsonType.RegularExpression:
+                    ReadRegularExpression();
+                    break;
+                case BsonType.String:
+                    ReadString();
+                    break;
+                case BsonType.Symbol:
+                    ReadSymbol();
+                    break;
+                case BsonType.Timestamp:
+                    ReadTimestamp();
+                    break;
+                case BsonType.Undefined:
+                    ReadUndefined();
+                    break;
+                default:
+                    throw new BsonInternalException("Invalid BsonType.");
+            }
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the reader.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                try
+                {
+                    Close();
+                }
+                catch { } // ignore exceptions
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private string FormatInvalidTokenMessage(JsonToken token)
+        {
+            return string.Format("Invalid JSON token: '{0}'", token.Lexeme);
+        }
+
+        private string FormatJavaScriptDateTimeString(DateTime dateTime)
+        {
+            var utc = BsonUtils.ToUniversalTime(dateTime);
+            var local = BsonUtils.ToLocalTime(utc);
+            var offset = local - utc;
+            var offsetSign = "+";
+            if (offset < TimeSpan.Zero)
+            {
+                offset = -offset;
+                offsetSign = "-";
+            }
+            var timeZone = TimeZone.CurrentTimeZone;
+            var timeZoneName = local.IsDaylightSavingTime() ? timeZone.DaylightName : timeZone.StandardName;
+            var dateTimeString = string.Format(
+                "{0} GMT{1}{2:D2}{3:D2} ({4})",
+                local.ToString("ddd MMM dd yyyy HH:mm:ss"), offsetSign, offset.Hours, offset.Minutes, timeZoneName);
+            return dateTimeString;
+        }
+
+        private BsonReaderState GetNextState()
+        {
+            switch (_context.ContextType)
+            {
+                case ContextType.Array:
+                case ContextType.Document:
+                    return BsonReaderState.Type;
+                case ContextType.TopLevel:
+                    return BsonReaderState.Done;
+                default:
+                    throw new BsonInternalException("Unexpected ContextType.");
+            }
+        }
+
+        private BsonValue ParseBinDataConstructor()
+        {
+            VerifyToken("(");
+            var subTypeToken = PopToken();
+            if (subTypeToken.Type != JsonTokenType.Int32)
+            {
+                var message = string.Format("JSON reader expected a binary subtype but found '{0}'.", subTypeToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(",");
+            var bytesToken = PopToken();
+            if (bytesToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", bytesToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            var bytes = Convert.FromBase64String(bytesToken.StringValue);
+            var subType = (BsonBinarySubType)subTypeToken.Int32Value;
+            GuidRepresentation guidRepresentation;
+            switch (subType)
+            {
+                case BsonBinarySubType.UuidLegacy: guidRepresentation = _jsonReaderSettings.GuidRepresentation; break;
+                case BsonBinarySubType.UuidStandard: guidRepresentation = GuidRepresentation.Standard; break;
+                default: guidRepresentation = GuidRepresentation.Unspecified; break;
+            }
+            return new BsonBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        private BsonValue ParseBinDataExtendedJson()
+        {
+            VerifyToken(":");
+            var bytesToken = PopToken();
+            if (bytesToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", bytesToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(",");
+            VerifyString("$type");
+            VerifyToken(":");
+            var subTypeToken = PopToken();
+            if (subTypeToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", subTypeToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            var bytes = Convert.FromBase64String(bytesToken.StringValue);
+            var subType = (BsonBinarySubType)Convert.ToInt32(subTypeToken.StringValue, 16);
+            GuidRepresentation guidRepresentation;
+            switch (subType)
+            {
+                case BsonBinarySubType.UuidLegacy: guidRepresentation = _jsonReaderSettings.GuidRepresentation; break;
+                case BsonBinarySubType.UuidStandard: guidRepresentation = GuidRepresentation.Standard; break;
+                default: guidRepresentation = GuidRepresentation.Unspecified; break;
+            }
+            return new BsonBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        private BsonValue ParseHexDataConstructor()
+        {
+            VerifyToken("(");
+            var subTypeToken = PopToken();
+            if (subTypeToken.Type != JsonTokenType.Int32)
+            {
+                var message = string.Format("JSON reader expected a binary subtype but found '{0}'.", subTypeToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(",");
+            var bytesToken = PopToken();
+            if (bytesToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", bytesToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            var bytes = BsonUtils.ParseHexString(bytesToken.StringValue);
+            var subType = (BsonBinarySubType)subTypeToken.Int32Value;
+            GuidRepresentation guidRepresentation;
+            switch (subType)
+            {
+                case BsonBinarySubType.UuidLegacy: guidRepresentation = _jsonReaderSettings.GuidRepresentation; break;
+                case BsonBinarySubType.UuidStandard: guidRepresentation = GuidRepresentation.Standard; break;
+                default: guidRepresentation = GuidRepresentation.Unspecified; break;
+            }
+            return new BsonBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        private BsonType ParseJavaScriptExtendedJson(out BsonValue value)
+        {
+            VerifyToken(":");
+            var codeToken = PopToken();
+            if (codeToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", codeToken.Lexeme);
+                throw new Exception(message);
+            }
+            var nextToken = PopToken();
+            switch (nextToken.Type)
+            {
+                case JsonTokenType.Comma:
+                    VerifyString("$scope");
+                    VerifyToken(":");
+                    State = BsonReaderState.Value;
+                    value = codeToken.StringValue;
+                    return BsonType.JavaScriptWithScope;
+                case JsonTokenType.EndObject:
+                    value = codeToken.StringValue;
+                    return BsonType.JavaScript;
+                default:
+                    var message = string.Format("JSON reader expected ',' or '}' but found '{0}'.", codeToken.Lexeme);
+                    throw new Exception(message);
+            }
+        }
+
+        private BsonValue ParseISODateTimeConstructor()
+        {
+            VerifyToken("(");
+            var valueToken = PopToken();
+            if (valueToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            var formats = new string[] { "yyyy-MM-ddK", "yyyy-MM-ddTHH:mm:ssK", "yyyy-MM-ddTHH:mm:ss.FFFFFFFK" };
+            var utcDateTime = DateTime.ParseExact(valueToken.StringValue, formats, null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
+            return new BsonDateTime(utcDateTime);
+        }
+
+        private BsonValue ParseDateTimeExtendedJson()
+        {
+            VerifyToken(":");
+            var valueToken = PopToken();
+
+            long millisecondsSinceEpoch;
+            if (valueToken.Type == JsonTokenType.Int32 || valueToken.Type == JsonTokenType.Int64)
+            {
+                millisecondsSinceEpoch = valueToken.Int64Value;
+            }
+            else if (valueToken.Type == JsonTokenType.String)
+            {
+                DateTime dateTime;
+                if (!DateTime.TryParse(valueToken.StringValue, out dateTime))
+                {
+                    var message = string.Format("Invalid $date string: '{0}'.", valueToken.StringValue);
+                    throw new Exception(message);
+                }
+                millisecondsSinceEpoch = BsonUtils.ToMillisecondsSinceEpoch(dateTime);
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer or an ISO 8601 string for $date but found a '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+
+            VerifyToken("}");
+            return new BsonDateTime(millisecondsSinceEpoch);
+        }
+
+        private BsonValue ParseDateTimeConstructor(bool withNew)
+        {
+            VerifyToken("(");
+
+            // Date when used without "new" behaves differently (JavaScript has some weird parts)
+            if (!withNew)
+            {
+                VerifyToken(")");
+                var dateTimeString = FormatJavaScriptDateTimeString(DateTime.UtcNow);
+                return new BsonString(dateTimeString);
+            }
+
+            var token = PopToken();
+            if (token.Lexeme == ")")
+            {
+                return new BsonDateTime(DateTime.UtcNow);
+            }
+            else if (token.Type == JsonTokenType.String)
+            {
+                VerifyToken(")");
+                var dateTimeString = token.StringValue;
+                var dateTime = ParseJavaScriptDateTimeString(dateTimeString);
+                return new BsonDateTime(dateTime);
+            }
+            else if (token.Type == JsonTokenType.Int32 || token.Type == JsonTokenType.Int64)
+            {
+                var args = new List<long>();
+                while (true)
+                {
+                    args.Add(token.Int64Value);
+                    token = PopToken();
+                    if (token.Lexeme == ")")
+                    {
+                        break;
+                    }
+                    if (token.Lexeme != ",")
+                    {
+                        var message = string.Format("JSON reader expected a ',' or a ')' but found '{0}'.", token.Lexeme);
+                        throw new Exception(message);
+                    }
+                    token = PopToken();
+                    if (token.Type != JsonTokenType.Int32 && token.Type != JsonTokenType.Int64)
+                    {
+                        var message = string.Format("JSON reader expected an integer but found '{0}'.", token.Lexeme);
+                        throw new Exception(message);
+                    }
+                }
+                switch (args.Count)
+                {
+                    case 1:
+                        return new BsonDateTime(args[0]);
+                    case 3:
+                    case 4:
+                    case 5:
+                    case 6:
+                    case 7:
+                        var year = (int)args[0];
+                        var month = (int)args[1] + 1; // JavaScript starts at 0 but .NET starts at 1
+                        var day = (int)args[2];
+                        var hours = (args.Count >= 4) ? (int)args[3] : 0;
+                        var minutes = (args.Count >= 5) ? (int)args[4] : 0;
+                        var seconds = (args.Count >= 6) ? (int)args[5] : 0;
+                        var milliseconds = (args.Count == 7) ? (int)args[6] : 0;
+                        var dateTime = new DateTime(year, month, day, hours, minutes, seconds, milliseconds, DateTimeKind.Utc);
+                        return new BsonDateTime(dateTime);
+                    default:
+                        var message = string.Format("JSON reader expected 1 or 3-7 integers but found {0}.", args.Count);
+                        throw new Exception(message);
+                }
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer or a string but found '{0}'.", token.Lexeme);
+                throw new Exception(message);
+            }
+        }
+
+        private BsonType ParseExtendedJson()
+        {
+            var nameToken = PopToken();
+            if (nameToken.Type == JsonTokenType.String || nameToken.Type == JsonTokenType.UnquotedString)
+            {
+                switch (nameToken.StringValue)
+                {
+                    case "$binary": _currentValue = ParseBinDataExtendedJson(); return BsonType.Binary;
+                    case "$code": return ParseJavaScriptExtendedJson(out _currentValue);
+                    case "$date": _currentValue = ParseDateTimeExtendedJson(); return BsonType.DateTime;
+                    case "$maxkey": case "$maxKey": _currentValue = ParseMaxKeyExtendedJson(); return BsonType.MaxKey;
+                    case "$minkey": case "$minKey": _currentValue = ParseMinKeyExtendedJson(); return BsonType.MinKey;
+                    case "$numberLong": _currentValue = ParseNumberLongExtendedJson(); return BsonType.Int64;
+                    case "$oid": _currentValue = ParseObjectIdExtendedJson(); return BsonType.ObjectId;
+                    case "$regex": _currentValue = ParseRegularExpressionExtendedJson(); return BsonType.RegularExpression;
+                    case "$symbol": _currentValue = ParseSymbolExtendedJson(); return BsonType.Symbol;
+                    case "$timestamp": _currentValue = ParseTimestampExtendedJson(); return BsonType.Timestamp;
+                    case "$undefined": _currentValue = ParseUndefinedExtendedJson(); return BsonType.Undefined;
+                }
+            }
+            PushToken(nameToken);
+            return BsonType.Document;
+        }
+
+        private DateTime ParseJavaScriptDateTimeString(string dateTimeString)
+        {
+            // if DateTime.TryParse succeeds we're done, otherwise assume it's an RFC 822 formatted DateTime string
+            DateTime dateTime;
+            if (DateTime.TryParse(dateTimeString, out dateTime))
+            {
+                return dateTime;
+            }
+            else
+            {
+                var rfc822DateTimePattern =
+                    @"^((?<dayOfWeek>(Mon|Tue|Wed|Thu|Fri|Sat|Sun)), )?" +
+                    @"(?<day>\d{1,2}) +" +
+                    @"(?<monthName>Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " +
+                    @"(?<year>\d{2}|\d{4}) " +
+                    @"(?<hour>\d{1,2}):" +
+                    @"(?<minutes>\d{1,2}):" +
+                    @"(?<seconds>\d{1,2}(.\d{1,7})?) " +
+                    @"(?<zone>UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-Z]|([+-]\d{4}))$";
+                var match = Regex.Match(dateTimeString, rfc822DateTimePattern);
+                if (match.Success)
+                {
+                    var day = int.Parse(match.Groups["day"].Value);
+
+                    int month;
+                    var monthName = match.Groups["monthName"].Value;
+                    switch (monthName)
+                    {
+                        case "Jan": month = 1; break;
+                        case "Feb": month = 2; break;
+                        case "Mar": month = 3; break;
+                        case "Apr": month = 4; break;
+                        case "May": month = 5; break;
+                        case "Jun": month = 6; break;
+                        case "Jul": month = 7; break;
+                        case "Aug": month = 8; break;
+                        case "Sep": month = 9; break;
+                        case "Oct": month = 10; break;
+                        case "Nov": month = 11; break;
+                        case "Dec": month = 12; break;
+                        default:
+                            var message = string.Format("\"{0}\" is not a valid RFC 822 month name.", monthName);
+                            throw new Exception(message);
+                    }
+
+                    var yearString = match.Groups["year"].Value;
+                    int year = int.Parse(yearString);
+                    if (yearString.Length == 2)
+                    {
+                        year += 2000;
+                        if (year - DateTime.UtcNow.Year >= 19) { year -= 100; }
+                    }
+
+                    var hour = int.Parse(match.Groups["hour"].Value);
+                    var minutes = int.Parse(match.Groups["minutes"].Value);
+                    var secondsString = match.Groups["seconds"].Value;
+                    int seconds;
+                    double milliseconds;
+                    if (secondsString.IndexOf('.') != -1)
+                    {
+                        var timeSpan = TimeSpan.FromSeconds(double.Parse(secondsString));
+                        seconds = timeSpan.Seconds;
+                        milliseconds = timeSpan.TotalMilliseconds - seconds * 1000;
+                    }
+                    else
+                    {
+                        seconds = int.Parse(secondsString);
+                        milliseconds = 0;
+                    }
+
+                    dateTime = new DateTime(year, month, day, hour, minutes, seconds, DateTimeKind.Utc).AddMilliseconds(milliseconds);
+
+                    // check day of week before converting to UTC
+                    var dayOfWeekString = match.Groups["dayOfWeek"].Value;
+                    if (dayOfWeekString != "")
+                    {
+                        DayOfWeek dayOfWeek;
+                        switch (dayOfWeekString)
+                        {
+                            case "Mon": dayOfWeek = DayOfWeek.Monday; break;
+                            case "Tue": dayOfWeek = DayOfWeek.Tuesday; break;
+                            case "Wed": dayOfWeek = DayOfWeek.Wednesday; break;
+                            case "Thu": dayOfWeek = DayOfWeek.Thursday; break;
+                            case "Fri": dayOfWeek = DayOfWeek.Friday; break;
+                            case "Sat": dayOfWeek = DayOfWeek.Saturday; break;
+                            case "Sun": dayOfWeek = DayOfWeek.Sunday; break;
+                            default:
+                                var message = string.Format("\"{0}\" is not a valid RFC 822 day name.", dayOfWeekString);
+                                throw new Exception(message);
+                        }
+                        if (dateTime.DayOfWeek != dayOfWeek)
+                        {
+                            var message = string.Format("\"{0}\" is not the right day of the week for {1}.", dayOfWeekString, dateTime.ToString("o"));
+                            throw new Exception(message);
+                        }
+                    }
+
+                    TimeSpan offset;
+                    var zone = match.Groups["zone"].Value;
+                    switch (zone)
+                    {
+                        case "UT": case "GMT": case "Z": offset = TimeSpan.Zero; break;
+                        case "EST": offset = TimeSpan.FromHours(-5); break;
+                        case "EDT": offset = TimeSpan.FromHours(-4); break;
+                        case "CST": offset = TimeSpan.FromHours(-6); break;
+                        case "CDT": offset = TimeSpan.FromHours(-5); break;
+                        case "MST": offset = TimeSpan.FromHours(-7); break;
+                        case "MDT": offset = TimeSpan.FromHours(-6); break;
+                        case "PST": offset = TimeSpan.FromHours(-8); break;
+                        case "PDT": offset = TimeSpan.FromHours(-7); break;
+                        case "A": offset = TimeSpan.FromHours(-1); break;
+                        case "B": offset = TimeSpan.FromHours(-2); break;
+                        case "C": offset = TimeSpan.FromHours(-3); break;
+                        case "D": offset = TimeSpan.FromHours(-4); break;
+                        case "E": offset = TimeSpan.FromHours(-5); break;
+                        case "F": offset = TimeSpan.FromHours(-6); break;
+                        case "G": offset = TimeSpan.FromHours(-7); break;
+                        case "H": offset = TimeSpan.FromHours(-8); break;
+                        case "I": offset = TimeSpan.FromHours(-9); break;
+                        case "K": offset = TimeSpan.FromHours(-10); break;
+                        case "L": offset = TimeSpan.FromHours(-11); break;
+                        case "M": offset = TimeSpan.FromHours(-12); break;
+                        case "N": offset = TimeSpan.FromHours(1); break;
+                        case "O": offset = TimeSpan.FromHours(2); break;
+                        case "P": offset = TimeSpan.FromHours(3); break;
+                        case "Q": offset = TimeSpan.FromHours(4); break;
+                        case "R": offset = TimeSpan.FromHours(5); break;
+                        case "S": offset = TimeSpan.FromHours(6); break;
+                        case "T": offset = TimeSpan.FromHours(7); break;
+                        case "U": offset = TimeSpan.FromHours(8); break;
+                        case "V": offset = TimeSpan.FromHours(9); break;
+                        case "W": offset = TimeSpan.FromHours(10); break;
+                        case "X": offset = TimeSpan.FromHours(11); break;
+                        case "Y": offset = TimeSpan.FromHours(12); break;
+                        default:
+                            var offsetSign = zone.Substring(0);
+                            var offsetHours = zone.Substring(1, 2);
+                            var offsetMinutes = zone.Substring(3, 2);
+                            offset = TimeSpan.FromHours(int.Parse(offsetHours)) + TimeSpan.FromMinutes(int.Parse(offsetMinutes));
+                            if (offsetSign == "-")
+                            {
+                                offset = -offset;
+                            }
+                            break;
+                    }
+
+                    return dateTime.Add(-offset);
+                }
+                else
+                {
+                    var message = string.Format("The DateTime string \"{0}\" is not a valid DateTime string for either .NET or JavaScript.", dateTimeString);
+                    throw new Exception(message);
+                }
+            }
+        }
+
+        private BsonValue ParseMaxKeyExtendedJson()
+        {
+            VerifyToken(":");
+            VerifyToken("1");
+            VerifyToken("}");
+            return BsonMaxKey.Value;
+        }
+
+        private BsonValue ParseMinKeyExtendedJson()
+        {
+            VerifyToken(":");
+            VerifyToken("1");
+            VerifyToken("}");
+            return BsonMinKey.Value;
+        }
+
+        private BsonType ParseNew(out BsonValue value)
+        {
+            var typeToken = PopToken();
+            if (typeToken.Type != JsonTokenType.UnquotedString)
+            {
+                var message = string.Format("JSON reader expected a type name but found '{0}'.", typeToken.Lexeme);
+                throw new Exception(message);
+            }
+            switch (typeToken.Lexeme)
+            {
+                case "BinData":
+                    value = ParseBinDataConstructor();
+                    return BsonType.Binary;
+                case "Date":
+                    value = ParseDateTimeConstructor(true); // withNew = true
+                    return BsonType.DateTime;
+                case "HexData":
+                    value = ParseHexDataConstructor();
+                    return BsonType.Binary;
+                case "ISODate":
+                    value = ParseISODateTimeConstructor();
+                    return BsonType.DateTime;
+                case "NumberInt":
+                    value = ParseNumberConstructor();
+                    return BsonType.Int32;
+                case "NumberLong":
+                    value = ParseNumberLongConstructor();
+                    return BsonType.Int64;
+                case "ObjectId":
+                    value = ParseObjectIdConstructor();
+                    return BsonType.ObjectId;
+                case "RegExp":
+                    value = ParseRegularExpressionConstructor();
+                    return BsonType.RegularExpression;
+                case "Timestamp":
+                    value = ParseTimestampConstructor();
+                    return BsonType.Timestamp;
+                case "UUID":
+                case "GUID":
+                case "CSUUID":
+                case "CSGUID":
+                case "JUUID":
+                case "JGUID":
+                case "PYUUID":
+                case "PYGUID":
+                    value = ParseUUIDConstructor(typeToken.Lexeme);
+                    return BsonType.Binary;
+                default:
+                    var message = string.Format("JSON reader expected a type name but found '{0}'.", typeToken.Lexeme);
+                    throw new Exception(message);
+            }
+        }
+
+        private BsonValue ParseNumberConstructor()
+        {
+            VerifyToken("(");
+            var valueToken = PopToken();
+            int value;
+            if (valueToken.IsNumber)
+            {
+                value = valueToken.Int32Value;
+            }
+            else if (valueToken.Type == JsonTokenType.String)
+            {
+                value = int.Parse(valueToken.StringValue);
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer or a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            return new BsonInt32(value);
+        }
+
+        private BsonValue ParseNumberLongConstructor()
+        {
+            VerifyToken("(");
+            var valueToken = PopToken();
+            long value;
+            if (valueToken.Type == JsonTokenType.Int32 || valueToken.Type == JsonTokenType.Int64)
+            {
+                value = valueToken.Int64Value;
+            }
+            else if (valueToken.Type == JsonTokenType.String)
+            {
+                value = long.Parse(valueToken.StringValue);
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer or a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            return new BsonInt64(value);
+        }
+
+        private BsonValue ParseNumberLongExtendedJson()
+        {
+            VerifyToken(":");
+            var valueToken = PopToken();
+            if (valueToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            return new BsonInt64(long.Parse(valueToken.StringValue));
+        }
+
+        private BsonValue ParseObjectIdConstructor()
+        {
+            VerifyToken("(");
+            var valueToken = PopToken();
+            if (valueToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            return new BsonObjectId(ObjectId.Parse(valueToken.StringValue));
+        }
+
+        private BsonValue ParseObjectIdExtendedJson()
+        {
+            VerifyToken(":");
+            var valueToken = PopToken();
+            if (valueToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            return new BsonObjectId(ObjectId.Parse(valueToken.StringValue));
+        }
+
+        private BsonValue ParseRegularExpressionConstructor()
+        {
+            VerifyToken("(");
+            var patternToken = PopToken();
+            if (patternToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", patternToken.Lexeme);
+                throw new Exception(message);
+            }
+            var options = "";
+            var commaToken = PopToken();
+            if (commaToken.Lexeme == ",")
+            {
+                var optionsToken = PopToken();
+                if (optionsToken.Type != JsonTokenType.String)
+                {
+                    var message = string.Format("JSON reader expected a string but found '{0}'.", optionsToken.Lexeme);
+                    throw new Exception(message);
+                }
+                options = optionsToken.StringValue;
+            }
+            else
+            {
+                PushToken(commaToken);
+            }
+            VerifyToken(")");
+            return new BsonRegularExpression(patternToken.StringValue, options);
+        }
+
+        private BsonValue ParseRegularExpressionExtendedJson()
+        {
+            VerifyToken(":");
+            var patternToken = PopToken();
+            if (patternToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", patternToken.Lexeme);
+                throw new Exception(message);
+            }
+            var options = "";
+            var commaToken = PopToken();
+            if (commaToken.Lexeme == ",")
+            {
+                VerifyString("$options");
+                VerifyToken(":");
+                var optionsToken = PopToken();
+                if (optionsToken.Type != JsonTokenType.String)
+                {
+                    var message = string.Format("JSON reader expected a string but found '{0}'.", optionsToken.Lexeme);
+                    throw new Exception(message);
+                }
+                options = optionsToken.StringValue;
+            }
+            else
+            {
+                PushToken(commaToken);
+            }
+            VerifyToken("}");
+            return new BsonRegularExpression(patternToken.StringValue, options);
+        }
+
+        private BsonValue ParseSymbolExtendedJson()
+        {
+            VerifyToken(":");
+            var nameToken = PopToken();
+            if (nameToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", nameToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            return new BsonString(nameToken.StringValue); // will be converted to a BsonSymbol at a higher level
+        }
+
+        private BsonValue ParseTimestampConstructor()
+        {
+            VerifyToken("(");
+            int secondsSinceEpoch;
+            var secondsSinceEpochToken = PopToken();
+            if (secondsSinceEpochToken.IsNumber)
+            {
+                secondsSinceEpoch = secondsSinceEpochToken.Int32Value;
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected a number but found '{0}'.", secondsSinceEpochToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(",");
+            int increment;
+            var incrementToken = PopToken();
+            if (secondsSinceEpochToken.IsNumber)
+            {
+                increment = incrementToken.Int32Value;
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected a number but found '{0}'.", secondsSinceEpochToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            return new BsonTimestamp(secondsSinceEpoch, increment);
+        }
+
+        private BsonValue ParseTimestampExtendedJson()
+        {
+            VerifyToken(":");
+            var nextToken = PopToken();
+            if (nextToken.Type == JsonTokenType.BeginObject)
+            {
+                return ParseTimestampExtendedJsonNewRepresentation();
+            }
+            else
+            {
+                return ParseTimestampExtendedJsonOldRepresentation(nextToken);
+            }
+        }
+
+        private BsonValue ParseTimestampExtendedJsonNewRepresentation()
+        {
+            VerifyString("t");
+            VerifyToken(":");
+            var secondsSinceEpochToken = PopToken();
+            int secondsSinceEpoch;
+            if (secondsSinceEpochToken.IsNumber)
+            {
+                secondsSinceEpoch = secondsSinceEpochToken.Int32Value;
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer but found '{0}'.", secondsSinceEpochToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(",");
+            VerifyString("i");
+            VerifyToken(":");
+            var incrementToken = PopToken();
+            int increment;
+            if (incrementToken.IsNumber)
+            {
+                increment = incrementToken.Int32Value;
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer but found '{0}'.", incrementToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            VerifyToken("}");
+            return new BsonTimestamp(secondsSinceEpoch, increment);
+        }
+
+        private BsonValue ParseTimestampExtendedJsonOldRepresentation(JsonToken valueToken)
+        {
+            long value;
+            if (valueToken.Type == JsonTokenType.Int32 || valueToken.Type == JsonTokenType.Int64)
+            {
+                value = valueToken.Int64Value;
+            }
+            else if (valueToken.Type == JsonTokenType.UnquotedString && valueToken.Lexeme == "NumberLong")
+            {
+                value = ParseNumberLongConstructor().AsInt64;
+            }
+            else
+            {
+                var message = string.Format("JSON reader expected an integer but found '{0}'.", valueToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken("}");
+            return new BsonTimestamp(value);
+        }
+
+        private BsonValue ParseUndefinedExtendedJson()
+        {
+            VerifyToken(":");
+            VerifyToken("true");
+            VerifyToken("}");
+            return BsonMaxKey.Value;
+        }
+
+        private BsonValue ParseUUIDConstructor(string uuidConstructorName)
+        {
+            VerifyToken("(");
+            var bytesToken = PopToken();
+            if (bytesToken.Type != JsonTokenType.String)
+            {
+                var message = string.Format("JSON reader expected a string but found '{0}'.", bytesToken.Lexeme);
+                throw new Exception(message);
+            }
+            VerifyToken(")");
+            var hexString = bytesToken.StringValue.Replace("{", "").Replace("}", "").Replace("-", "");
+            var bytes = BsonUtils.ParseHexString(hexString);
+            var guid = GuidConverter.FromBytes(bytes, GuidRepresentation.Standard);
+            GuidRepresentation guidRepresentation;
+            switch (uuidConstructorName)
+            {
+                case "CSUUID":
+                case "CSGUID":
+                    guidRepresentation = GuidRepresentation.CSharpLegacy;
+                    break;
+                case "JUUID":
+                case "JGUID":
+                    guidRepresentation = GuidRepresentation.JavaLegacy;
+                    break;
+                case "PYUUID":
+                case "PYGUID":
+                    guidRepresentation = GuidRepresentation.PythonLegacy;
+                    break;
+                case "UUID":
+                case "GUID":
+                    guidRepresentation = GuidRepresentation.Standard;
+                    break;
+                default:
+                    throw new BsonInternalException("Unexpected uuidConstructorName");
+            }
+            bytes = GuidConverter.ToBytes(guid, guidRepresentation);
+            var subType = (guidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
+            return new BsonBinaryData(bytes, subType, guidRepresentation);
+        }
+
+        private JsonToken PopToken()
+        {
+            if (_pushedToken != null)
+            {
+                var token = _pushedToken;
+                _pushedToken = null;
+                return token;
+            }
+            else
+            {
+                return JsonScanner.GetNextToken(_buffer);
+            }
+        }
+
+        private void PushToken(JsonToken token)
+        {
+            if (_pushedToken == null)
+            {
+                _pushedToken = token;
+            }
+            else
+            {
+                throw new BsonInternalException("There is already a pending token.");
+            }
+        }
+
+        private void VerifyString(string expectedString)
+        {
+            var token = PopToken();
+            if ((token.Type != JsonTokenType.String && token.Type != JsonTokenType.UnquotedString) || token.StringValue != expectedString)
+            {
+                var message = string.Format("JSON reader expected '{0}' but found '{1}'.", expectedString, token.StringValue);
+                throw new Exception(message);
+            }
+        }
+
+        private void VerifyToken(string expectedLexeme)
+        {
+            var token = PopToken();
+            if (token.Lexeme != expectedLexeme)
+            {
+                var message = string.Format("JSON reader expected '{0}' but found '{1}'.", expectedLexeme, token.Lexeme);
+                throw new Exception(message);
+            }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReader.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4f5f0314e1defc541b7a3dbe0c9849f7
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 76 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderBookmark.cs

@@ -0,0 +1,76 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a bookmark that can be used to return a reader to the current position and state.
+    /// </summary>
+    public class JsonReaderBookmark : BsonReaderBookmark
+    {
+        // private fields
+        private JsonReaderContext _context;
+        private JsonToken _currentToken;
+        private BsonValue _currentValue;
+        private JsonToken _pushedToken;
+        private int _position;
+
+        // constructors
+        internal JsonReaderBookmark(
+            BsonReaderState state,
+            BsonType currentBsonType,
+            string currentName,
+            JsonReaderContext context,
+            JsonToken currentToken,
+            BsonValue currentValue,
+            JsonToken pushedToken,
+            int position)
+            : base(state, currentBsonType, currentName)
+        {
+            _context = context.Clone();
+            _currentToken = currentToken;
+            _currentValue = currentValue;
+            _pushedToken = pushedToken;
+            _position = position;
+        }
+
+        // internal properties
+        internal JsonToken CurrentToken
+        {
+            get { return _currentToken; }
+        }
+
+        internal BsonValue CurrentValue
+        {
+            get { return _currentValue; }
+        }
+
+        internal int Position
+        {
+            get { return _position; }
+        }
+
+        internal JsonToken PushedToken
+        {
+            get { return _pushedToken; }
+        }
+
+        // internal methods
+        internal JsonReaderContext CloneContext()
+        {
+            return _context.Clone();
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderBookmark.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f2397142720b8f847bdbd5315a2c24af
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 57 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderContext.cs

@@ -0,0 +1,57 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    internal class JsonReaderContext
+    {
+        // private fields
+        private JsonReaderContext _parentContext;
+        private ContextType _contextType;
+
+        // constructors
+        // used by Clone
+        private JsonReaderContext()
+        {
+        }
+
+        internal JsonReaderContext(JsonReaderContext parentContext, ContextType contextType)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+        }
+
+        // internal properties
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the context.
+        /// </summary>
+        /// <returns>A clone of the context.</returns>
+        public JsonReaderContext Clone()
+        {
+            return new JsonReaderContext(_parentContext, _contextType);
+        }
+
+        public JsonReaderContext PopContext()
+        {
+            return _parentContext;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1c476ca02cb704643bc71a2d85d0a8e9
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 108 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderSettings.cs

@@ -0,0 +1,108 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents settings for a JsonReader.
+    /// </summary>
+    [Serializable]
+    public class JsonReaderSettings : BsonReaderSettings
+    {
+        // private static fields
+        private static JsonReaderSettings __defaults = null; // delay creation to pick up the latest default values
+
+        // private fields
+        private bool _closeInput = false;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the JsonReaderSettings class.
+        /// </summary>
+        public JsonReaderSettings()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the JsonReaderSettings class.
+        /// </summary>
+        /// <param name="closeInput">Whether to close the input stream when the reader is closed.</param>
+        /// <param name="guidRepresentation">The representation for Guids.</param>
+        [Obsolete("Use the no-argument constructor instead and set the properties.")]
+        public JsonReaderSettings(bool closeInput, GuidRepresentation guidRepresentation)
+            : base(guidRepresentation)
+        {
+            _closeInput = closeInput;
+        }
+
+        // public static properties
+        /// <summary>
+        /// Gets or sets the default settings for a JsonReader.
+        /// </summary>
+        public static JsonReaderSettings Defaults
+        {
+            get
+            {
+                if (__defaults == null)
+                {
+                    __defaults = new JsonReaderSettings();
+                }
+                return __defaults;
+            }
+            set { __defaults = value; }
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets or sets whether to close the input stream when the reader is closed.
+        /// </summary>
+        public bool CloseInput
+        {
+            get { return _closeInput; }
+            set
+            {
+                if (IsFrozen) { throw new InvalidOperationException("JsonReaderSettings is frozen."); }
+                _closeInput = value;
+            }
+        }
+
+        // public methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        public new JsonReaderSettings Clone()
+        {
+            return (JsonReaderSettings)CloneImplementation();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Creates a clone of the settings.
+        /// </summary>
+        /// <returns>A clone of the settings.</returns>
+        protected override BsonReaderSettings CloneImplementation()
+        {
+            var clone = new JsonReaderSettings
+            {
+                CloseInput = _closeInput,
+                GuidRepresentation = GuidRepresentation
+            };
+            return clone;
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonReaderSettings.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 31df3ee570aba8240b8b29e09a697e59
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 532 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonScanner.cs

@@ -0,0 +1,532 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// A static class that represents a JSON scanner.
+    /// </summary>
+    public static class JsonScanner
+    {
+        // public static methods
+        /// <summary>
+        /// Gets the next JsonToken from a JsonBuffer.
+        /// </summary>
+        /// <param name="buffer">The buffer.</param>
+        /// <returns>The next token.</returns>
+        public static JsonToken GetNextToken(JsonBuffer buffer)
+        {
+            // skip leading whitespace
+            var c = buffer.Read();
+            while (c != -1 && char.IsWhiteSpace((char)c))
+            {
+                c = buffer.Read();
+            }
+            if (c == -1)
+            {
+                return new JsonToken(JsonTokenType.EndOfFile, "<eof>");
+            }
+
+            // leading character determines token type
+            switch (c)
+            {
+                case '{': return new JsonToken(JsonTokenType.BeginObject, "{");
+                case '}': return new JsonToken(JsonTokenType.EndObject, "}");
+                case '[': return new JsonToken(JsonTokenType.BeginArray, "[");
+                case ']': return new JsonToken(JsonTokenType.EndArray, "]");
+                case '(': return new JsonToken(JsonTokenType.LeftParen, "(");
+                case ')': return new JsonToken(JsonTokenType.RightParen, ")");
+                case ':': return new JsonToken(JsonTokenType.Colon, ":");
+                case ',': return new JsonToken(JsonTokenType.Comma, ",");
+                case '\'':
+                case '"':
+                    return GetStringToken(buffer, (char)c);
+                case '/': return GetRegularExpressionToken(buffer);
+                default:
+                    if (c == '-' || char.IsDigit((char)c))
+                    {
+                        return GetNumberToken(buffer, c);
+                    }
+                    else if (c == '$' || c == '_' || char.IsLetter((char)c))
+                    {
+                        return GetUnquotedStringToken(buffer);
+                    }
+                    else
+                    {
+                        buffer.UnRead(c);
+                        throw new Exception(FormatMessage("Invalid JSON input", buffer, buffer.Position));
+                    }
+            }
+        }
+
+        // private methods
+        private static string FormatMessage(string message, JsonBuffer buffer, int start)
+        {
+            var length = 20;
+            string snippet;
+            if (buffer.Position + length >= buffer.Length)
+            {
+                snippet = buffer.Substring(start);
+            }
+            else
+            {
+                snippet = buffer.Substring(start, length) + "...";
+            }
+            return string.Format("{0} '{1}'.", message, snippet);
+        }
+
+        private static JsonToken GetNumberToken(JsonBuffer buffer, int firstChar)
+        {
+            var c = firstChar;
+
+            // leading digit or '-' has already been read
+            var start = buffer.Position - 1;
+            NumberState state;
+            switch (c)
+            {
+                case '-': state = NumberState.SawLeadingMinus; break;
+                case '0': state = NumberState.SawLeadingZero; break;
+                default: state = NumberState.SawIntegerDigits; break;
+            }
+            var type = JsonTokenType.Int64; // assume integer until proved otherwise
+
+            while (true)
+            {
+                c = buffer.Read();
+                switch (state)
+                {
+                    case NumberState.SawLeadingMinus:
+                        switch (c)
+                        {
+                            case '0':
+                                state = NumberState.SawLeadingZero;
+                                break;
+                            case 'I':
+                                state = NumberState.SawMinusI;
+                                break;
+                            default:
+                                if (char.IsDigit((char)c))
+                                {
+                                    state = NumberState.SawIntegerDigits;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawLeadingZero:
+                        switch (c)
+                        {
+                            case '.':
+                                state = NumberState.SawDecimalPoint;
+                                break;
+                            case 'e':
+                            case 'E':
+                                state = NumberState.SawExponentLetter;
+                                break;
+                            case ',':
+                            case '}':
+                            case ']':
+                            case ')':
+                            case -1:
+                                state = NumberState.Done;
+                                break;
+                            default:
+                                if (char.IsWhiteSpace((char)c))
+                                {
+                                    state = NumberState.Done;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawIntegerDigits:
+                        switch (c)
+                        {
+                            case '.':
+                                state = NumberState.SawDecimalPoint;
+                                break;
+                            case 'e':
+                            case 'E':
+                                state = NumberState.SawExponentLetter;
+                                break;
+                            case ',':
+                            case '}':
+                            case ']':
+                            case ')':
+                            case -1:
+                                state = NumberState.Done;
+                                break;
+                            default:
+                                if (char.IsDigit((char)c))
+                                {
+                                    state = NumberState.SawIntegerDigits;
+                                }
+                                else if (char.IsWhiteSpace((char)c))
+                                {
+                                    state = NumberState.Done;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawDecimalPoint:
+                        type = JsonTokenType.Double;
+                        if (char.IsDigit((char)c))
+                        {
+                            state = NumberState.SawFractionDigits;
+                        }
+                        else
+                        {
+                            state = NumberState.Invalid;
+                        }
+                        break;
+                    case NumberState.SawFractionDigits:
+                        switch (c)
+                        {
+                            case 'e':
+                            case 'E':
+                                state = NumberState.SawExponentLetter;
+                                break;
+                            case ',':
+                            case '}':
+                            case ']':
+                            case ')':
+                            case -1:
+                                state = NumberState.Done;
+                                break;
+                            default:
+                                if (char.IsDigit((char)c))
+                                {
+                                    state = NumberState.SawFractionDigits;
+                                }
+                                else if (char.IsWhiteSpace((char)c))
+                                {
+                                    state = NumberState.Done;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawExponentLetter:
+                        type = JsonTokenType.Double;
+                        switch (c)
+                        {
+                            case '+':
+                            case '-':
+                                state = NumberState.SawExponentSign;
+                                break;
+                            default:
+                                if (char.IsDigit((char)c))
+                                {
+                                    state = NumberState.SawExponentDigits;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawExponentSign:
+                        if (char.IsDigit((char)c))
+                        {
+                            state = NumberState.SawExponentDigits;
+                        }
+                        else
+                        {
+                            state = NumberState.Invalid;
+                        }
+                        break;
+                    case NumberState.SawExponentDigits:
+                        switch (c)
+                        {
+                            case ',':
+                            case '}':
+                            case ']':
+                            case ')':
+                            case -1:
+                                state = NumberState.Done;
+                                break;
+                            default:
+                                if (char.IsDigit((char)c))
+                                {
+                                    state = NumberState.SawExponentDigits;
+                                }
+                                else if (char.IsWhiteSpace((char)c))
+                                {
+                                    state = NumberState.Done;
+                                }
+                                else
+                                {
+                                    state = NumberState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                    case NumberState.SawMinusI:
+                        var sawMinusInfinity = true;
+                        var nfinity = new char[] { 'n', 'f', 'i', 'n', 'i', 't', 'y' };
+                        for (var i = 0; i < nfinity.Length; i++)
+                        {
+                            if (c != nfinity[i])
+                            {
+                                sawMinusInfinity = false;
+                                break;
+                            }
+                            c = buffer.Read();
+                        }
+                        if (sawMinusInfinity)
+                        {
+                            type = JsonTokenType.Double;
+                            switch (c)
+                            {
+                                case ',':
+                                case '}':
+                                case ']':
+                                case ')':
+                                case -1:
+                                    state = NumberState.Done;
+                                    break;
+                                default:
+                                    if (char.IsWhiteSpace((char)c))
+                                    {
+                                        state = NumberState.Done;
+                                    }
+                                    else
+                                    {
+                                        state = NumberState.Invalid;
+                                    }
+                                    break;
+                            }
+                        }
+                        else
+                        {
+                            state = NumberState.Invalid;
+                        }
+                        break;
+                }
+
+                switch (state)
+                {
+                    case NumberState.Done:
+                        buffer.UnRead(c);
+                        var lexeme = buffer.Substring(start, buffer.Position - start);
+                        if (type == JsonTokenType.Double)
+                        {
+                            var value = XmlConvert.ToDouble(lexeme);
+                            return new DoubleJsonToken(lexeme, value);
+                        }
+                        else
+                        {
+                            var value = XmlConvert.ToInt64(lexeme);
+                            if (value < int.MinValue || value > int.MaxValue)
+                            {
+                                return new Int64JsonToken(lexeme, value);
+                            }
+                            else
+                            {
+                                return new Int32JsonToken(lexeme, (int)value);
+                            }
+                        }
+                    case NumberState.Invalid:
+                        throw new Exception(FormatMessage("Invalid JSON number", buffer, start));
+                }
+            }
+        }
+
+        private static JsonToken GetRegularExpressionToken(JsonBuffer buffer)
+        {
+            // opening slash has already been read
+            var start = buffer.Position - 1;
+            var state = RegularExpressionState.InPattern;
+            while (true)
+            {
+                var c = buffer.Read();
+                switch (state)
+                {
+                    case RegularExpressionState.InPattern:
+                        switch (c)
+                        {
+                            case '/': state = RegularExpressionState.InOptions; break;
+                            case '\\': state = RegularExpressionState.InEscapeSequence; break;
+                            default: state = RegularExpressionState.InPattern; break;
+                        }
+                        break;
+                    case RegularExpressionState.InEscapeSequence:
+                        state = RegularExpressionState.InPattern;
+                        break;
+                    case RegularExpressionState.InOptions:
+                        switch (c)
+                        {
+                            case 'i':
+                            case 'm':
+                            case 'x':
+                            case 's':
+                                state = RegularExpressionState.InOptions;
+                                break;
+                            case ',':
+                            case '}':
+                            case ']':
+                            case ')':
+                            case -1:
+                                state = RegularExpressionState.Done;
+                                break;
+                            default:
+                                if (char.IsWhiteSpace((char)c))
+                                {
+                                    state = RegularExpressionState.Done;
+                                }
+                                else
+                                {
+                                    state = RegularExpressionState.Invalid;
+                                }
+                                break;
+                        }
+                        break;
+                }
+
+                switch (state)
+                {
+                    case RegularExpressionState.Done:
+                        buffer.UnRead(c);
+                        var lexeme = buffer.Substring(start, buffer.Position - start);
+                        var regex = new BsonRegularExpression(lexeme);
+                        return new RegularExpressionJsonToken(lexeme, regex);
+                    case RegularExpressionState.Invalid:
+                        throw new Exception(FormatMessage("Invalid JSON regular expression", buffer, start));
+                }
+            }
+        }
+
+        private static JsonToken GetStringToken(JsonBuffer buffer, char quoteCharacter)
+        {
+            // opening quote has already been read
+            var start = buffer.Position - 1;
+            var sb = new StringBuilder();
+            while (true)
+            {
+                var c = buffer.Read();
+                switch (c)
+                {
+                    case '\\':
+                        c = buffer.Read();
+                        switch (c)
+                        {
+                            case '\'': sb.Append('\''); break;
+                            case '"': sb.Append('"'); break;
+                            case '\\': sb.Append('\\'); break;
+                            case '/': sb.Append('/'); break;
+                            case 'b': sb.Append('\b'); break;
+                            case 'f': sb.Append('\f'); break;
+                            case 'n': sb.Append('\n'); break;
+                            case 'r': sb.Append('\r'); break;
+                            case 't': sb.Append('\t'); break;
+                            case 'u':
+                                var u1 = buffer.Read();
+                                var u2 = buffer.Read();
+                                var u3 = buffer.Read();
+                                var u4 = buffer.Read();
+                                if (u4 != -1)
+                                {
+                                    var hex = new string(new char[] { (char)u1, (char)u2, (char)u3, (char)u4 });
+                                    var n = Convert.ToInt32(hex, 16);
+                                    sb.Append((char)n);
+                                }
+                                break;
+                            default:
+                                if (c != -1)
+                                {
+                                    var message = string.Format("Invalid escape sequence in JSON string '\\{0}'.", (char)c);
+                                    throw new Exception(message);
+                                }
+                                break;
+                        }
+                        break;
+                    default:
+                        if (c == quoteCharacter)
+                        {
+                            var lexeme = buffer.Substring(start, buffer.Position - start);
+                            return new StringJsonToken(JsonTokenType.String, lexeme, sb.ToString());
+                        }
+                        if (c != -1)
+                        {
+                            sb.Append((char)c);
+                        }
+                        break;
+                }
+                if (c == -1)
+                {
+                    throw new Exception(FormatMessage("End of file in JSON string.", buffer, start));
+                }
+            }
+        }
+
+        private static JsonToken GetUnquotedStringToken(JsonBuffer buffer)
+        {
+            // opening letter or $ has already been read
+            var start = buffer.Position - 1;
+            var c = buffer.Read();
+            while (c == '$' || c == '_' || char.IsLetterOrDigit((char)c))
+            {
+                c = buffer.Read();
+            }
+            buffer.UnRead(c);
+            var lexeme = buffer.Substring(start, buffer.Position - start);
+            return new StringJsonToken(JsonTokenType.UnquotedString, lexeme, lexeme);
+        }
+
+        // nested types
+        private enum NumberState
+        {
+            SawLeadingMinus,
+            SawLeadingZero,
+            SawIntegerDigits,
+            SawDecimalPoint,
+            SawFractionDigits,
+            SawExponentLetter,
+            SawExponentSign,
+            SawExponentDigits,
+            SawMinusI,
+            Done,
+            Invalid
+        }
+
+        private enum RegularExpressionState
+        {
+            InPattern,
+            InEscapeSequence,
+            InOptions,
+            Done,
+            Invalid
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonScanner.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 335faefeab13c1f448b777915b30d9fc
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 496 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonToken.cs

@@ -0,0 +1,496 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a JSON token type.
+    /// </summary>
+    public enum JsonTokenType
+    {
+        /// <summary>
+        /// An invalid token.
+        /// </summary>
+        Invalid,
+        /// <summary>
+        /// A begin array token (a '[').
+        /// </summary>
+        BeginArray,
+        /// <summary>
+        /// A begin object token (a '{').
+        /// </summary>
+        BeginObject,
+        /// <summary>
+        /// An end array token (a ']').
+        /// </summary>
+        EndArray,
+        /// <summary>
+        /// A left parenthesis (a '(').
+        /// </summary>
+        LeftParen,
+        /// <summary>
+        /// A right parenthesis (a ')').
+        /// </summary>
+        RightParen,
+        /// <summary>
+        /// An end object token (a '}').
+        /// </summary>
+        EndObject,
+        /// <summary>
+        /// A colon token (a ':').
+        /// </summary>
+        Colon,
+        /// <summary>
+        /// A comma token (a ',').
+        /// </summary>
+        Comma,
+        /// <summary>
+        /// A DateTime token.
+        /// </summary>
+        DateTime,
+        /// <summary>
+        /// A Double token.
+        /// </summary>
+        Double,
+        /// <summary>
+        /// An Int32 token.
+        /// </summary>
+        Int32,
+        /// <summary>
+        /// And Int64 token.
+        /// </summary>
+        Int64,
+        /// <summary>
+        /// An ObjectId token.
+        /// </summary>
+        ObjectId,
+        /// <summary>
+        /// A regular expression token.
+        /// </summary>
+        RegularExpression,
+        /// <summary>
+        /// A string token.
+        /// </summary>
+        String,
+        /// <summary>
+        /// An unquoted string token.
+        /// </summary>
+        UnquotedString,
+        /// <summary>
+        /// An end of file token.
+        /// </summary>
+        EndOfFile
+    }
+
+    /// <summary>
+    /// Represents a JSON token.
+    /// </summary>
+    public class JsonToken
+    {
+        // private fields
+        private JsonTokenType _type;
+        private string _lexeme;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the JsonToken class.
+        /// </summary>
+        /// <param name="type">The token type.</param>
+        /// <param name="lexeme">The lexeme.</param>
+        public JsonToken(JsonTokenType type, string lexeme)
+        {
+            _type = type;
+            _lexeme = lexeme;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the token type.
+        /// </summary>
+        public JsonTokenType Type
+        {
+            get { return _type; }
+        }
+
+        /// <summary>
+        /// Gets the lexeme.
+        /// </summary>
+        public string Lexeme
+        {
+            get { return _lexeme; }
+        }
+
+        /// <summary>
+        /// Gets the value of a DateTime token.
+        /// </summary>
+        public virtual BsonDateTime DateTimeValue
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets the value of a Double token.
+        /// </summary>
+        public virtual double DoubleValue
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int32 token.
+        /// </summary>
+        public virtual int Int32Value
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int64 token.
+        /// </summary>
+        public virtual long Int64Value
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this token is number.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this token is number; otherwise, <c>false</c>.
+        /// </value>
+        public virtual bool IsNumber
+        {
+            get { return false; }
+        }
+
+        /// <summary>
+        /// Gets the value of an ObjectId token.
+        /// </summary>
+        public virtual ObjectId ObjectIdValue
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets the value of a regular expression token.
+        /// </summary>
+        public virtual BsonRegularExpression RegularExpressionValue
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        /// <summary>
+        /// Gets the value of a string token.
+        /// </summary>
+        public virtual string StringValue
+        {
+            get { throw new NotSupportedException(); }
+        }
+    }
+
+    /// <summary>
+    /// Represents a DateTime JSON token.
+    /// </summary>
+    public class DateTimeJsonToken : JsonToken
+    {
+        // private fields
+        private BsonDateTime _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the DateTimeJsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The DateTime value.</param>
+        public DateTimeJsonToken(string lexeme, BsonDateTime value)
+            : base(JsonTokenType.DateTime, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of a DateTime token.
+        /// </summary>
+        public override BsonDateTime DateTimeValue
+        {
+            get { return _value; }
+        }
+    }
+
+    /// <summary>
+    /// Represents a Double JSON token.
+    /// </summary>
+    public class DoubleJsonToken : JsonToken
+    {
+        // private fields
+        private double _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the DoubleJsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The Double value.</param>
+        public DoubleJsonToken(string lexeme, double value)
+            : base(JsonTokenType.Double, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of a Double token.
+        /// </summary>
+        public override double DoubleValue
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int32 token.
+        /// </summary>
+        public override int Int32Value
+        {
+            get { return (int)_value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int64 token.
+        /// </summary>
+        public override long Int64Value
+        {
+            get { return (long)_value; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this token is number.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this token is number; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsNumber
+        {
+            get { return true; }
+        }
+    }
+
+    /// <summary>
+    /// Represents an Int32 JSON token.
+    /// </summary>
+    public class Int32JsonToken : JsonToken
+    {
+        // private fields
+        private int _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the Int32JsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The Int32 value.</param>
+        public Int32JsonToken(string lexeme, int value)
+            : base(JsonTokenType.Int32, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of a Double token.
+        /// </summary>
+        public override double DoubleValue
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int32 token.
+        /// </summary>
+        public override int Int32Value
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int32 token as an Int64.
+        /// </summary>
+        public override long Int64Value
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this token is number.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this token is number; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsNumber
+        {
+            get { return true; }
+        }
+    }
+
+    /// <summary>
+    /// Represents an Int64 JSON token.
+    /// </summary>
+    public class Int64JsonToken : JsonToken
+    {
+        // private fields
+        private long _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the Int64JsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The Int64 value.</param>
+        public Int64JsonToken(string lexeme, long value)
+            : base(JsonTokenType.Int64, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of a Double token.
+        /// </summary>
+        public override double DoubleValue
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int32 token.
+        /// </summary>
+        public override int Int32Value
+        {
+            get { return (int)_value; }
+        }
+
+        /// <summary>
+        /// Gets the value of an Int64 token.
+        /// </summary>
+        public override long Int64Value
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this token is number.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this token is number; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsNumber
+        {
+            get { return true; }
+        }
+    }
+
+    /// <summary>
+    /// Represents an ObjectId JSON token.
+    /// </summary>
+    public class ObjectIdJsonToken : JsonToken
+    {
+        // private fields
+        private ObjectId _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the ObjectIdJsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The ObjectId value.</param>
+        public ObjectIdJsonToken(string lexeme, ObjectId value)
+            : base(JsonTokenType.ObjectId, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of an ObjectId token.
+        /// </summary>
+        public override ObjectId ObjectIdValue
+        {
+            get { return _value; }
+        }
+    }
+
+    /// <summary>
+    /// Represents a regular expression JSON token.
+    /// </summary>
+    public class RegularExpressionJsonToken : JsonToken
+    {
+        // private fields
+        private BsonRegularExpression _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the RegularExpressionJsonToken class.
+        /// </summary>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The BsonRegularExpression value.</param>
+        public RegularExpressionJsonToken(string lexeme, BsonRegularExpression value)
+            : base(JsonTokenType.RegularExpression, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of a regular expression token.
+        /// </summary>
+        public override BsonRegularExpression RegularExpressionValue
+        {
+            get { return _value; }
+        }
+    }
+
+    /// <summary>
+    /// Represents a String JSON token.
+    /// </summary>
+    public class StringJsonToken : JsonToken
+    {
+        // private fields
+        private string _value;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the StringJsonToken class.
+        /// </summary>
+        /// <param name="type">The token type.</param>
+        /// <param name="lexeme">The lexeme.</param>
+        /// <param name="value">The String value.</param>
+        public StringJsonToken(JsonTokenType type, string lexeme, string value)
+            : base(type, lexeme)
+        {
+            _value = value;
+        }
+
+        // public properties
+        /// <summary>
+        /// Gets the value of an String token.
+        /// </summary>
+        public override string StringValue
+        {
+            get { return _value; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonToken.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c9be03243037932438e2540816b73c09
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 855 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriter.cs

@@ -0,0 +1,855 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace MongoDB.Bson.IO
+{
+    /// <summary>
+    /// Represents a BSON writer to a TextWriter (in JSON format).
+    /// </summary>
+    public class JsonWriter : BsonWriter
+    {
+        // private fields
+        private TextWriter _textWriter;
+        private JsonWriterSettings _jsonWriterSettings; // same value as in base class just declared as derived class
+        private JsonWriterContext _context;
+
+        // constructors
+        /// <summary>
+        /// Initializes a new instance of the JsonWriter class.
+        /// </summary>
+        /// <param name="writer">A TextWriter.</param>
+        /// <param name="settings">Optional JsonWriter settings.</param>
+        public JsonWriter(TextWriter writer, JsonWriterSettings settings)
+            : base(settings)
+        {
+            if (writer == null)
+            {
+                throw new ArgumentNullException("writer");
+            }
+
+            _textWriter = writer;
+            _jsonWriterSettings = settings; // already frozen by base class
+            _context = new JsonWriterContext(null, ContextType.TopLevel, "");
+            State = BsonWriterState.Initial;
+        }
+
+        // public methods
+        /// <summary>
+        /// Closes the writer.
+        /// </summary>
+        public override void Close()
+        {
+            // Close can be called on Disposed objects
+            if (State != BsonWriterState.Closed)
+            {
+                Flush();
+                if (_jsonWriterSettings.CloseOutput)
+                {
+                    _textWriter.Close();
+                }
+                _context = null;
+                State = BsonWriterState.Closed;
+            }
+        }
+
+        /// <summary>
+        /// Flushes any pending data to the output destination.
+        /// </summary>
+        public override void Flush()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            _textWriter.Flush();
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        public override void WriteBinaryData(BsonBinaryData binaryData)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteBinaryData", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            var subType = binaryData.SubType;
+            var bytes = binaryData.Bytes;
+            var guidRepresentation = binaryData.GuidRepresentation;
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{{ \"$binary\" : \"{0}\", \"$type\" : \"{1}\" }}", Convert.ToBase64String(bytes), ((int)subType).ToString("x2"));
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    switch (subType)
+                    {
+                        case BsonBinarySubType.UuidLegacy:
+                        case BsonBinarySubType.UuidStandard:
+                            _textWriter.Write(GuidToString(subType, bytes, guidRepresentation));
+                            break;
+
+                        default:
+                        _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes));
+                            break;
+                    }
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Boolean to the writer.
+        /// </summary>
+        /// <param name="value">The Boolean value.</param>
+        public override void WriteBoolean(bool value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteBoolean", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write(value ? "true" : "false");
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes BSON binary data to the writer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        public override void WriteBytes(byte[] bytes)
+        {
+            WriteBinaryData(new BsonBinaryData(bytes, BsonBinarySubType.Binary));
+        }
+
+        /// <summary>
+        /// Writes a BSON DateTime to the writer.
+        /// </summary>
+        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
+        public override void WriteDateTime(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteDateTime", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{{ \"$date\" : {0} }}", value);
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    // use ISODate for values that fall within .NET's DateTime range, and "new Date" for all others
+                    if (value >= BsonConstants.DateTimeMinValueMillisecondsSinceEpoch &&
+                        value <= BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
+                    {
+                        var utcDateTime = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(value);
+                        _textWriter.Write("ISODate(\"{0}\")", utcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ"));
+                    }
+                    else
+                    {
+                        _textWriter.Write("new Date({0})", value);
+                    }
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Double to the writer.
+        /// </summary>
+        /// <param name="value">The Double value.</param>
+        public override void WriteDouble(double value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteDouble", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            // if string representation looks like an integer add ".0" so that it looks like a double
+            var stringRepresentation = value.ToString("R", NumberFormatInfo.InvariantInfo);
+            if (Regex.IsMatch(stringRepresentation, @"^[+-]?\d+$"))
+            {
+                stringRepresentation += ".0";
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write(stringRepresentation);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON array to the writer.
+        /// </summary>
+        public override void WriteEndArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value)
+            {
+                ThrowInvalidState("WriteEndArray", BsonWriterState.Value);
+            }
+
+            base.WriteEndArray();
+            _textWriter.Write("]");
+
+            _context = _context.ParentContext;
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the end of a BSON document to the writer.
+        /// </summary>
+        public override void WriteEndDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Name)
+            {
+                ThrowInvalidState("WriteEndDocument", BsonWriterState.Name);
+            }
+
+            base.WriteEndDocument();
+            if (_jsonWriterSettings.Indent && _context.HasElements)
+            {
+                _textWriter.Write(_jsonWriterSettings.NewLineChars);
+                if (_context.ParentContext != null)
+                {
+                    _textWriter.Write(_context.ParentContext.Indentation);
+                }
+                _textWriter.Write("}");
+            }
+            else
+            {
+                _textWriter.Write(" }");
+            }
+
+            if (_context.ContextType == ContextType.ScopeDocument)
+            {
+                _context = _context.ParentContext;
+                WriteEndDocument();
+            }
+            else
+            {
+                _context = _context.ParentContext;
+            }
+
+            if (_context == null)
+            {
+                State = BsonWriterState.Done;
+            }
+            else
+            {
+                State = GetNextState();
+            }
+        }
+
+        /// <summary>
+        /// Writes a BSON Int32 to the writer.
+        /// </summary>
+        /// <param name="value">The Int32 value.</param>
+        public override void WriteInt32(int value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteInt32", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Int64 to the writer.
+        /// </summary>
+        /// <param name="value">The Int64 value.</param>
+        public override void WriteInt64(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteInt64", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write(value);
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    if (value >= int.MinValue && value <= int.MaxValue)
+                    {
+                        _textWriter.Write("NumberLong({0})", value);
+                    }
+                    else
+                    {
+                        _textWriter.Write("NumberLong(\"{0}\")", value);
+                    }
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer.
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScript(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteJavaScript", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write("{{ \"$code\" : \"{0}\" }}", EscapedString(code));
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON JavaScript to the writer (call WriteStartDocument to start writing the scope).
+        /// </summary>
+        /// <param name="code">The JavaScript code.</param>
+        public override void WriteJavaScriptWithScope(string code)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteJavaScriptWithScope", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteStartDocument();
+            WriteString("$code", code);
+            WriteName("$scope");
+
+            State = BsonWriterState.ScopeDocument;
+        }
+
+        /// <summary>
+        /// Writes a BSON MaxKey to the writer.
+        /// </summary>
+        public override void WriteMaxKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteMaxKey", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{ \"$maxKey\" : 1 }");
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    _textWriter.Write("MaxKey");
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON MinKey to the writer.
+        /// </summary>
+        public override void WriteMinKey()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteMinKey", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{ \"$minKey\" : 1 }");
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    _textWriter.Write("MinKey");
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON null to the writer.
+        /// </summary>
+        public override void WriteNull()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteNull", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write("null");
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON ObjectId to the writer.
+        /// </summary>
+        /// <param name="objectId">The ObjectId.</param>
+        public override void WriteObjectId(ObjectId objectId)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteObjectId", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            var bytes = ObjectId.Pack(objectId.Timestamp, objectId.Machine, objectId.Pid, objectId.Increment);
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{{ \"$oid\" : \"{0}\" }}", BsonUtils.ToHexString(bytes));
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    _textWriter.Write("ObjectId(\"{0}\")", BsonUtils.ToHexString(bytes));
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON regular expression to the writer.
+        /// </summary>
+        /// <param name="regex">A BsonRegularExpression.</param>
+        public override void WriteRegularExpression(BsonRegularExpression regex)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteRegularExpression", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            var pattern = regex.Pattern;
+            var options = regex.Options;
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{{ \"$regex\" : \"{0}\", \"$options\" : \"{1}\" }}", EscapedString(pattern), EscapedString(options));
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    var escapedPattern = (pattern == "") ? "(?:)" : pattern.Replace("/", @"\/");
+                    _textWriter.Write("/{0}/{1}", escapedPattern, options);
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON array to the writer.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteStartArray", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            base.WriteStartArray();
+            WriteNameHelper(Name);
+            _textWriter.Write("[");
+
+            _context = new JsonWriterContext(_context, ContextType.Array, _jsonWriterSettings.IndentChars);
+            State = BsonWriterState.Value;
+        }
+
+        /// <summary>
+        /// Writes the start of a BSON document to the writer.
+        /// </summary>
+        public override void WriteStartDocument()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial && State != BsonWriterState.ScopeDocument)
+            {
+                ThrowInvalidState("WriteStartDocument", BsonWriterState.Value, BsonWriterState.Initial, BsonWriterState.ScopeDocument);
+            }
+
+            base.WriteStartDocument();
+            if (State == BsonWriterState.Value || State == BsonWriterState.ScopeDocument)
+            {
+                WriteNameHelper(Name);
+            }
+            _textWriter.Write("{");
+
+            var contextType = (State == BsonWriterState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document;
+            _context = new JsonWriterContext(_context, contextType, _jsonWriterSettings.IndentChars);
+            State = BsonWriterState.Name;
+        }
+
+        /// <summary>
+        /// Writes a BSON String to the writer.
+        /// </summary>
+        /// <param name="value">The String value.</param>
+        public override void WriteString(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteString", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            WriteQuotedString(value);
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON Symbol to the writer.
+        /// </summary>
+        /// <param name="value">The symbol.</param>
+        public override void WriteSymbol(string value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteSymbol", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            _textWriter.Write("{{ \"$symbol\" : \"{0}\" }}", EscapedString(value));
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON timestamp to the writer.
+        /// </summary>
+        /// <param name="value">The combined timestamp/increment value.</param>
+        public override void WriteTimestamp(long value)
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteTimestamp", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            var secondsSinceEpoch = (int)((value >> 32) & 0xffffffff);
+            var increment = (int)(value & 0xffffffff);
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{{ \"$timestamp\" : {{ \"t\" : {0}, \"i\" : {1} }} }}", secondsSinceEpoch, increment);
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    _textWriter.Write("Timestamp({0}, {1})", secondsSinceEpoch, increment);
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        /// <summary>
+        /// Writes a BSON undefined to the writer.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
+            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
+            {
+                ThrowInvalidState("WriteUndefined", BsonWriterState.Value, BsonWriterState.Initial);
+            }
+
+            WriteNameHelper(Name);
+            switch (_jsonWriterSettings.OutputMode)
+            {
+                case JsonOutputMode.Strict:
+                    _textWriter.Write("{ \"$undefined\" : true }");
+                    break;
+
+                case JsonOutputMode.Shell:
+                default:
+                    _textWriter.Write("undefined");
+                    break;
+            }
+
+            State = GetNextState();
+        }
+
+        // protected methods
+        /// <summary>
+        /// Disposes of any resources used by the writer.
+        /// </summary>
+        /// <param name="disposing">True if called from Dispose.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Close();
+                _textWriter.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        // private methods
+        private string EscapedString(string value)
+        {
+            if (value.All(c => !NeedsEscaping(c)))
+            {
+                return value;
+            }
+
+            var sb = new StringBuilder(value.Length);
+
+            foreach (char c in value)
+            {
+                switch (c)
+                {
+                    case '"': sb.Append("\\\""); break;
+                    case '\\': sb.Append("\\\\"); break;
+                    case '\b': sb.Append("\\b"); break;
+                    case '\f': sb.Append("\\f"); break;
+                    case '\n': sb.Append("\\n"); break;
+                    case '\r': sb.Append("\\r"); break;
+                    case '\t': sb.Append("\\t"); break;
+                    default:
+                        switch (char.GetUnicodeCategory(c))
+                        {
+                            case UnicodeCategory.UppercaseLetter:
+                            case UnicodeCategory.LowercaseLetter:
+                            case UnicodeCategory.TitlecaseLetter:
+                            case UnicodeCategory.OtherLetter:
+                            case UnicodeCategory.DecimalDigitNumber:
+                            case UnicodeCategory.LetterNumber:
+                            case UnicodeCategory.OtherNumber:
+                            case UnicodeCategory.SpaceSeparator:
+                            case UnicodeCategory.ConnectorPunctuation:
+                            case UnicodeCategory.DashPunctuation:
+                            case UnicodeCategory.OpenPunctuation:
+                            case UnicodeCategory.ClosePunctuation:
+                            case UnicodeCategory.InitialQuotePunctuation:
+                            case UnicodeCategory.FinalQuotePunctuation:
+                            case UnicodeCategory.OtherPunctuation:
+                            case UnicodeCategory.MathSymbol:
+                            case UnicodeCategory.CurrencySymbol:
+                            case UnicodeCategory.ModifierSymbol:
+                            case UnicodeCategory.OtherSymbol:
+                                sb.Append(c);
+                                break;
+                            default:
+                                sb.AppendFormat("\\u{0:x4}", (int)c);
+                                break;
+                        }
+                        break;
+                }
+            }
+
+            return sb.ToString();
+        }
+
+        private BsonWriterState GetNextState()
+        {
+            if (_context.ContextType == ContextType.Array)
+            {
+                return BsonWriterState.Value;
+            }
+            else
+            {
+                return BsonWriterState.Name;
+            }
+        }
+
+        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 && 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 (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 bool NeedsEscaping(char c)
+        {
+            switch (c)
+            {
+                case '"':
+                case '\\':
+                case '\b':
+                case '\f':
+                case '\n':
+                case '\r':
+                case '\t':
+                    return true;
+
+                default:
+                    switch (char.GetUnicodeCategory(c))
+                    {
+                        case UnicodeCategory.UppercaseLetter:
+                        case UnicodeCategory.LowercaseLetter:
+                        case UnicodeCategory.TitlecaseLetter:
+                        case UnicodeCategory.OtherLetter:
+                        case UnicodeCategory.DecimalDigitNumber:
+                        case UnicodeCategory.LetterNumber:
+                        case UnicodeCategory.OtherNumber:
+                        case UnicodeCategory.SpaceSeparator:
+                        case UnicodeCategory.ConnectorPunctuation:
+                        case UnicodeCategory.DashPunctuation:
+                        case UnicodeCategory.OpenPunctuation:
+                        case UnicodeCategory.ClosePunctuation:
+                        case UnicodeCategory.InitialQuotePunctuation:
+                        case UnicodeCategory.FinalQuotePunctuation:
+                        case UnicodeCategory.OtherPunctuation:
+                        case UnicodeCategory.MathSymbol:
+                        case UnicodeCategory.CurrencySymbol:
+                        case UnicodeCategory.ModifierSymbol:
+                        case UnicodeCategory.OtherSymbol:
+                            return false;
+
+                        default:
+                            return true;
+                    }
+            }
+        }
+
+        private void WriteNameHelper(string name)
+        {
+            switch (_context.ContextType)
+            {
+                case ContextType.Array:
+                    // don't write Array element names in Json
+                    if (_context.HasElements)
+                    {
+                        _textWriter.Write(", ");
+                    }
+                    break;
+                case ContextType.Document:
+                case ContextType.ScopeDocument:
+                    if (_context.HasElements)
+                    {
+                        _textWriter.Write(",");
+                    }
+                    if (_jsonWriterSettings.Indent)
+                    {
+                        _textWriter.Write(_jsonWriterSettings.NewLineChars);
+                        _textWriter.Write(_context.Indentation);
+                    }
+                    else
+                    {
+                        _textWriter.Write(" ");
+                    }
+                    WriteQuotedString(name);
+                    _textWriter.Write(" : ");
+                    break;
+                case ContextType.TopLevel:
+                    break;
+                default:
+                    throw new BsonInternalException("Invalid ContextType.");
+            }
+
+            _context.HasElements = true;
+        }
+
+        private void WriteQuotedString(string value)
+        {
+            _textWriter.Write("\"");
+            _textWriter.Write(EscapedString(value));
+            _textWriter.Write("\"");
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriter.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2499ff95a40fdf14d83033734dbd068b
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 56 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriterContext.cs

@@ -0,0 +1,56 @@
+/* Copyright 2010-2014 MongoDB Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace MongoDB.Bson.IO
+{
+    internal class JsonWriterContext
+    {
+        // private fields
+        private JsonWriterContext _parentContext;
+        private ContextType _contextType;
+        private string _indentation;
+        private bool _hasElements = false;
+
+        // constructors
+        internal JsonWriterContext(JsonWriterContext parentContext, ContextType contextType, string indentChars)
+        {
+            _parentContext = parentContext;
+            _contextType = contextType;
+            _indentation = (parentContext == null) ? indentChars : parentContext.Indentation + indentChars;
+        }
+
+        // internal properties
+        internal JsonWriterContext ParentContext
+        {
+            get { return _parentContext; }
+        }
+
+        internal ContextType ContextType
+        {
+            get { return _contextType; }
+        }
+
+        internal string Indentation
+        {
+            get { return _indentation; }
+        }
+
+        internal bool HasElements
+        {
+            get { return _hasElements; }
+            set { _hasElements = value; }
+        }
+    }
+}

+ 8 - 0
Unity/Assets/Plugins/MongoDB/MongoDB.Bson/IO/JsonWriterContext.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 33a2f6d082da96b45a1e03dca878d92b
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů