BsonReader.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.IO;
  18. using System.Linq;
  19. using MongoDB.Bson.Serialization;
  20. using MongoDB.Bson.Serialization.Serializers;
  21. namespace MongoDB.Bson.IO
  22. {
  23. /// <summary>
  24. /// Represents a BSON reader for some external format (see subclasses).
  25. /// </summary>
  26. public abstract class BsonReader : IBsonReader
  27. {
  28. // private fields
  29. private bool _disposed = false;
  30. private BsonReaderSettings _settings;
  31. private BsonReaderState _state;
  32. private BsonType _currentBsonType;
  33. private string _currentName;
  34. private readonly Stack<BsonReaderSettings> _settingsStack = new Stack<BsonReaderSettings>();
  35. // constructors
  36. /// <summary>
  37. /// Initializes a new instance of the BsonReader class.
  38. /// </summary>
  39. /// <param name="settings">The reader settings.</param>
  40. protected BsonReader(BsonReaderSettings settings)
  41. {
  42. if (settings == null)
  43. {
  44. throw new ArgumentNullException("settings");
  45. }
  46. _settings = settings.FrozenCopy();
  47. _state = BsonReaderState.Initial;
  48. }
  49. // public properties
  50. /// <summary>
  51. /// Gets the current BsonType.
  52. /// </summary>
  53. public BsonType CurrentBsonType
  54. {
  55. get { return _currentBsonType; }
  56. protected set { _currentBsonType = value; }
  57. }
  58. /// <summary>
  59. /// Gets the settings of the reader.
  60. /// </summary>
  61. public BsonReaderSettings Settings
  62. {
  63. get { return _settings; }
  64. }
  65. /// <summary>
  66. /// Gets the current state of the reader.
  67. /// </summary>
  68. public BsonReaderState State
  69. {
  70. get { return _state; }
  71. protected set { _state = value; }
  72. }
  73. // protected properties
  74. /// <summary>
  75. /// Gets the current name.
  76. /// </summary>
  77. protected string CurrentName
  78. {
  79. get { return _currentName; }
  80. set { _currentName = value; }
  81. }
  82. /// <summary>
  83. /// Gets whether the BsonReader has been disposed.
  84. /// </summary>
  85. protected bool Disposed
  86. {
  87. get { return _disposed; }
  88. }
  89. // public methods
  90. /// <summary>
  91. /// Closes the reader.
  92. /// </summary>
  93. public abstract void Close();
  94. /// <summary>
  95. /// Disposes of any resources used by the reader.
  96. /// </summary>
  97. public void Dispose()
  98. {
  99. if (!_disposed)
  100. {
  101. Dispose(true);
  102. _disposed = true;
  103. }
  104. }
  105. /// <summary>
  106. /// Gets a bookmark to the reader's current position and state.
  107. /// </summary>
  108. /// <returns>A bookmark.</returns>
  109. public abstract BsonReaderBookmark GetBookmark();
  110. /// <summary>
  111. /// Gets the current BsonType (calls ReadBsonType if necessary).
  112. /// </summary>
  113. /// <returns>The current BsonType.</returns>
  114. public BsonType GetCurrentBsonType()
  115. {
  116. if (_state == BsonReaderState.Initial || _state == BsonReaderState.ScopeDocument || _state == BsonReaderState.Type)
  117. {
  118. ReadBsonType();
  119. }
  120. if (_state != BsonReaderState.Value)
  121. {
  122. ThrowInvalidState("GetCurrentBsonType", BsonReaderState.Value);
  123. }
  124. return _currentBsonType;
  125. }
  126. /// <summary>
  127. /// Determines whether this reader is at end of file.
  128. /// </summary>
  129. /// <returns>
  130. /// Whether this reader is at end of file.
  131. /// </returns>
  132. public abstract bool IsAtEndOfFile();
  133. /// <inheritdoc/>
  134. public void PopSettings()
  135. {
  136. _settings = _settingsStack.Pop();
  137. }
  138. /// <inheritdoc/>
  139. public void PushSettings(Action<BsonReaderSettings> configurator)
  140. {
  141. var newSettings = _settings.Clone();
  142. configurator(newSettings);
  143. newSettings.Freeze();
  144. _settingsStack.Push(_settings);
  145. _settings = newSettings;
  146. }
  147. /// <summary>
  148. /// Reads BSON binary data from the reader.
  149. /// </summary>
  150. /// <returns>A BsonBinaryData.</returns>
  151. public abstract BsonBinaryData ReadBinaryData();
  152. /// <summary>
  153. /// Reads a BSON boolean from the reader.
  154. /// </summary>
  155. /// <returns>A Boolean.</returns>
  156. public abstract bool ReadBoolean();
  157. /// <summary>
  158. /// Reads a BsonType from the reader.
  159. /// </summary>
  160. /// <returns>A BsonType.</returns>
  161. public abstract BsonType ReadBsonType();
  162. /// <summary>
  163. /// Reads BSON binary data from the reader.
  164. /// </summary>
  165. /// <returns>A byte array.</returns>
  166. public abstract byte[] ReadBytes();
  167. /// <summary>
  168. /// Reads a BSON DateTime from the reader.
  169. /// </summary>
  170. /// <returns>The number of milliseconds since the Unix epoch.</returns>
  171. public abstract long ReadDateTime();
  172. /// <inheritdoc />
  173. public abstract Decimal128 ReadDecimal128();
  174. /// <summary>
  175. /// Reads a BSON Double from the reader.
  176. /// </summary>
  177. /// <returns>A Double.</returns>
  178. public abstract double ReadDouble();
  179. /// <summary>
  180. /// Reads the end of a BSON array from the reader.
  181. /// </summary>
  182. public abstract void ReadEndArray();
  183. /// <summary>
  184. /// Reads the end of a BSON document from the reader.
  185. /// </summary>
  186. public abstract void ReadEndDocument();
  187. /// <summary>
  188. /// Reads a BSON Int32 from the reader.
  189. /// </summary>
  190. /// <returns>An Int32.</returns>
  191. public abstract int ReadInt32();
  192. /// <summary>
  193. /// Reads a BSON Int64 from the reader.
  194. /// </summary>
  195. /// <returns>An Int64.</returns>
  196. public abstract long ReadInt64();
  197. /// <summary>
  198. /// Reads a BSON JavaScript from the reader.
  199. /// </summary>
  200. /// <returns>A string.</returns>
  201. public abstract string ReadJavaScript();
  202. /// <summary>
  203. /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
  204. /// </summary>
  205. /// <returns>A string.</returns>
  206. public abstract string ReadJavaScriptWithScope();
  207. /// <summary>
  208. /// Reads a BSON MaxKey from the reader.
  209. /// </summary>
  210. public abstract void ReadMaxKey();
  211. /// <summary>
  212. /// Reads a BSON MinKey from the reader.
  213. /// </summary>
  214. public abstract void ReadMinKey();
  215. /// <summary>
  216. /// Reads the name of an element from the reader.
  217. /// </summary>
  218. /// <returns>The name of the element.</returns>
  219. public virtual string ReadName()
  220. {
  221. return ReadName(Utf8NameDecoder.Instance);
  222. }
  223. /// <summary>
  224. /// Reads the name of an element from the reader (using the provided name decoder).
  225. /// </summary>
  226. /// <param name="nameDecoder">The name decoder.</param>
  227. /// <returns>
  228. /// The name of the element.
  229. /// </returns>
  230. public abstract string ReadName(INameDecoder nameDecoder);
  231. /// <summary>
  232. /// Reads a BSON null from the reader.
  233. /// </summary>
  234. public abstract void ReadNull();
  235. /// <summary>
  236. /// Reads a BSON ObjectId from the reader.
  237. /// </summary>
  238. /// <returns>An ObjectId.</returns>
  239. public abstract ObjectId ReadObjectId();
  240. /// <summary>
  241. /// Reads a raw BSON array.
  242. /// </summary>
  243. /// <returns>The raw BSON array.</returns>
  244. public virtual IByteBuffer ReadRawBsonArray()
  245. {
  246. // overridden in BsonBinaryReader to read the raw bytes from the stream
  247. // for all other streams, deserialize the array and reserialize it using a BsonBinaryWriter to get the raw bytes
  248. var deserializationContext = BsonDeserializationContext.CreateRoot(this);
  249. var array = BsonArraySerializer.Instance.Deserialize(deserializationContext);
  250. using (var memoryStream = new MemoryStream())
  251. using (var bsonWriter = new BsonBinaryWriter(memoryStream, BsonBinaryWriterSettings.Defaults))
  252. {
  253. var serializationContext = BsonSerializationContext.CreateRoot(bsonWriter);
  254. bsonWriter.WriteStartDocument();
  255. var startPosition = memoryStream.Position + 3; // just past BsonType, "x" and null byte
  256. bsonWriter.WriteName("x");
  257. BsonArraySerializer.Instance.Serialize(serializationContext, array);
  258. var endPosition = memoryStream.Position;
  259. bsonWriter.WriteEndDocument();
  260. byte[] memoryStreamBuffer;
  261. memoryStreamBuffer = memoryStream.GetBuffer();
  262. var buffer = new ByteArrayBuffer(memoryStreamBuffer, (int)memoryStream.Length, isReadOnly: true);
  263. return new ByteBufferSlice(buffer, (int)startPosition, (int)(endPosition - startPosition));
  264. }
  265. }
  266. /// <summary>
  267. /// Reads a raw BSON document.
  268. /// </summary>
  269. /// <returns>The raw BSON document.</returns>
  270. public virtual IByteBuffer ReadRawBsonDocument()
  271. {
  272. // overridden in BsonBinaryReader to read the raw bytes from the stream
  273. // for all other streams, deserialize the document and use ToBson to get the raw bytes
  274. var deserializationContext = BsonDeserializationContext.CreateRoot(this);
  275. var document = BsonDocumentSerializer.Instance.Deserialize(deserializationContext);
  276. var bytes = document.ToBson();
  277. return new ByteArrayBuffer(bytes, isReadOnly: true);
  278. }
  279. /// <summary>
  280. /// Reads a BSON regular expression from the reader.
  281. /// </summary>
  282. /// <returns>A BsonRegularExpression.</returns>
  283. public abstract BsonRegularExpression ReadRegularExpression();
  284. /// <summary>
  285. /// Reads the start of a BSON array.
  286. /// </summary>
  287. public abstract void ReadStartArray();
  288. /// <summary>
  289. /// Reads the start of a BSON document.
  290. /// </summary>
  291. public abstract void ReadStartDocument();
  292. /// <summary>
  293. /// Reads a BSON string from the reader.
  294. /// </summary>
  295. /// <returns>A String.</returns>
  296. public abstract string ReadString();
  297. /// <summary>
  298. /// Reads a BSON symbol from the reader.
  299. /// </summary>
  300. /// <returns>A string.</returns>
  301. public abstract string ReadSymbol();
  302. /// <summary>
  303. /// Reads a BSON timestamp from the reader.
  304. /// </summary>
  305. /// <returns>The combined timestamp/increment.</returns>
  306. public abstract long ReadTimestamp();
  307. /// <summary>
  308. /// Reads a BSON undefined from the reader.
  309. /// </summary>
  310. public abstract void ReadUndefined();
  311. /// <summary>
  312. /// Returns the reader to previously bookmarked position and state.
  313. /// </summary>
  314. /// <param name="bookmark">The bookmark.</param>
  315. public abstract void ReturnToBookmark(BsonReaderBookmark bookmark);
  316. /// <summary>
  317. /// Skips the name (reader must be positioned on a name).
  318. /// </summary>
  319. public abstract void SkipName();
  320. /// <summary>
  321. /// Skips the value (reader must be positioned on a value).
  322. /// </summary>
  323. public abstract void SkipValue();
  324. // protected methods
  325. /// <summary>
  326. /// Disposes of any resources used by the reader.
  327. /// </summary>
  328. /// <param name="disposing">True if called from Dispose.</param>
  329. protected virtual void Dispose(bool disposing)
  330. {
  331. }
  332. /// <summary>
  333. /// Throws an InvalidOperationException when the method called is not valid for the current ContextType.
  334. /// </summary>
  335. /// <param name="methodName">The name of the method.</param>
  336. /// <param name="actualContextType">The actual ContextType.</param>
  337. /// <param name="validContextTypes">The valid ContextTypes.</param>
  338. protected void ThrowInvalidContextType(
  339. string methodName,
  340. ContextType actualContextType,
  341. params ContextType[] validContextTypes)
  342. {
  343. var validContextTypesString = string.Join(" or ", validContextTypes.Select(c => c.ToString()).ToArray());
  344. var message = string.Format(
  345. "{0} can only be called when ContextType is {1}, not when ContextType is {2}.",
  346. methodName, validContextTypesString, actualContextType);
  347. throw new InvalidOperationException(message);
  348. }
  349. /// <summary>
  350. /// Throws an InvalidOperationException when the method called is not valid for the current state.
  351. /// </summary>
  352. /// <param name="methodName">The name of the method.</param>
  353. /// <param name="validStates">The valid states.</param>
  354. protected void ThrowInvalidState(string methodName, params BsonReaderState[] validStates)
  355. {
  356. var validStatesString = string.Join(" or ", validStates.Select(s => s.ToString()).ToArray());
  357. var message = string.Format(
  358. "{0} can only be called when State is {1}, not when State is {2}.",
  359. methodName, validStatesString, _state);
  360. throw new InvalidOperationException(message);
  361. }
  362. /// <summary>
  363. /// Throws an ObjectDisposedException.
  364. /// </summary>
  365. protected void ThrowObjectDisposedException()
  366. {
  367. throw new ObjectDisposedException(this.GetType().Name);
  368. }
  369. /// <summary>
  370. /// Verifies the current state and BsonType of the reader.
  371. /// </summary>
  372. /// <param name="methodName">The name of the method calling this one.</param>
  373. /// <param name="requiredBsonType">The required BSON type.</param>
  374. protected void VerifyBsonType(string methodName, BsonType requiredBsonType)
  375. {
  376. if (_state == BsonReaderState.Initial || _state == BsonReaderState.ScopeDocument || _state == BsonReaderState.Type)
  377. {
  378. ReadBsonType();
  379. }
  380. if (_state == BsonReaderState.Name)
  381. {
  382. // ignore name
  383. SkipName();
  384. }
  385. if (_state != BsonReaderState.Value)
  386. {
  387. ThrowInvalidState(methodName, BsonReaderState.Value);
  388. }
  389. if (_currentBsonType != requiredBsonType)
  390. {
  391. var message = string.Format(
  392. "{0} can only be called when CurrentBsonType is {1}, not when CurrentBsonType is {2}.",
  393. methodName, requiredBsonType, _currentBsonType);
  394. throw new InvalidOperationException(message);
  395. }
  396. }
  397. }
  398. }