PageRenderTime 35ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/SharpDX/Serialization/BinarySerializer.cs

https://github.com/KarimLUCCIN/SharpDX
C# | 2838 lines | 1877 code | 358 blank | 603 comment | 271 complexity | fd263dfbb644ab642c1f1ef74ec2b5d8 MD5 | raw file
Possible License(s): Unlicense, AGPL-3.0, GPL-2.0, CC-BY-SA-3.0
  1. // Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. using System;
  21. using System.Collections.Generic;
  22. using System.IO;
  23. using System.Text;
  24. using SharpDX.IO;
  25. using SharpDX.Multimedia;
  26. using System.Reflection;
  27. namespace SharpDX.Serialization
  28. {
  29. /// <summary>
  30. /// Serializer action.
  31. /// </summary>
  32. /// <param name="value">The value to read or write.</param>
  33. /// <param name="serializer">The serializer.</param>
  34. public delegate void SerializerAction(ref object value, BinarySerializer serializer);
  35. /// <summary>
  36. /// This class provides serialization methods for types implementing the <see cref="IDataSerializable"/>.
  37. /// </summary>
  38. /// <remarks>
  39. /// BinarySerializer is a basic binary serializer with the following features:
  40. /// <ul>
  41. /// <li>10x times faster and smaller than default System Serialization and Xml Serialization.</li>
  42. /// <li>Supports for all primitive types, array/List&lt;T&gt;/Dictionary of primitive types, custom data via <see cref="IDataSerializable"/> (struct or class) and array/List/Dictionary of custom data.</li>
  43. /// <li>Optimized binary format, data serialized to the strict minimum.</li>
  44. /// <li>Should be compatible with Win8/WinRT, Desktop.</li>
  45. /// <li>Not reflection based serializer, but fully compile time serializer.</li>
  46. /// <li>Format could be read back from C/C++.</li>
  47. ///
  48. /// </ul>
  49. /// </remarks>
  50. public class BinarySerializer : Component
  51. {
  52. private int chunkCount;
  53. private Chunk[] chunks;
  54. private Chunk currentChunk;
  55. private readonly Dictionary<FourCC, Dynamic> dynamicMapToType;
  56. private readonly Dictionary<Type, Dynamic> dynamicMapToFourCC;
  57. private readonly Dictionary<object, int> objectToPosition;
  58. private readonly Dictionary<int, object> positionToObject;
  59. private Dictionary<object, object> mapTag;
  60. private int allowIdentityReferenceCount;
  61. // Fields used to serialize strings
  62. private System.Text.Encoding encoding;
  63. private System.Text.Encoder encoder;
  64. private System.Text.Decoder decoder;
  65. private const int LargeByteBufferSize = 1024;
  66. private byte[] largeByteBuffer;
  67. private int maxChars; // max # of chars we can put in _largeByteBuffer
  68. private char[] largeCharBuffer;
  69. private int maxCharSize; // From LargeByteBufferSize & Encoding
  70. public delegate void SerializerPrimitiveAction<T>(ref T value);
  71. public delegate void SerializerTypeAction<T>(ref T value, BinarySerializer serializer);
  72. public delegate object ReadRef(BinarySerializer serializer);
  73. public delegate void WriteRef(object value, BinarySerializer serializer);
  74. /// <summary>
  75. /// Underlying stream this instance is reading/writing to.
  76. /// </summary>
  77. public Stream Stream { get; private set; }
  78. /// <summary>
  79. /// Reader used to directly read from the underlying stream.
  80. /// </summary>
  81. public BinaryReader Reader { get; private set; }
  82. /// <summary>
  83. /// Gets the reader and throws an exception if this serializer is in Write mode.
  84. /// </summary>
  85. /// <param name="context">The context object that requires a Reader.</param>
  86. /// <returns>A BinaryReader.</returns>
  87. /// <exception cref="System.ArgumentNullException">context</exception>
  88. /// <exception cref="System.InvalidOperationException">If this reader is not in read mode</exception>
  89. public BinaryReader ReaderOnly(object context)
  90. {
  91. if (context == null)
  92. {
  93. throw new ArgumentNullException("context");
  94. }
  95. if (Mode != SerializerMode.Read)
  96. {
  97. throw new InvalidOperationException(string.Format("[{0}] is only expecting Read-Only BinarySerializer", context.GetType().Name));
  98. }
  99. return Reader;
  100. }
  101. /// <summary>
  102. /// Writer used to directly write to the underlying stream.
  103. /// </summary>
  104. public BinaryWriter Writer { get; private set; }
  105. public ArrayLengthType ArrayLengthType { get; set; }
  106. private SerializerMode mode;
  107. /// <summary>
  108. /// Initializes a new instance of the <see cref="BinarySerializer" /> class.
  109. /// </summary>
  110. /// <param name="stream">The stream to read or write to.</param>
  111. /// <param name="mode">The read or write mode.</param>
  112. public BinarySerializer(Stream stream, SerializerMode mode) : this(stream, mode, SharpDX.Text.Encoding.ASCII)
  113. {
  114. }
  115. /// <summary>
  116. /// Initializes a new instance of the <see cref="BinarySerializer" /> class.
  117. /// </summary>
  118. /// <param name="stream">The stream to read or write to.</param>
  119. /// <param name="mode">The read or write mode.</param>
  120. /// <param name="encoding">Default encoding used for strings. This parameter can be overriden later using Encoding property.</param>
  121. public BinarySerializer(Stream stream, SerializerMode mode, System.Text.Encoding encoding)
  122. {
  123. // Setup the encoding used for strings.
  124. Encoding = encoding;
  125. // Allocate dictionary used for dynamic serialization.
  126. dynamicMapToType = new Dictionary<FourCC, Dynamic>();
  127. dynamicMapToFourCC = new Dictionary<Type, Dynamic>();
  128. // For serializing reference
  129. objectToPosition = new Dictionary<object, int>(new IdentityEqualityComparer<object>());
  130. positionToObject = new Dictionary<int, object>();
  131. // Allocate the chunk array and initial chunk.
  132. chunks = new Chunk[8];
  133. Stream = stream;
  134. // Setup the mode.
  135. Mode = mode;
  136. CurrentChunk = new Chunk { ChunkIndexStart = 0 };
  137. chunks[chunkCount] = CurrentChunk;
  138. chunkCount++;
  139. // Register all default dynamics.
  140. foreach (var defaultDynamic in DefaultDynamics)
  141. RegisterDynamic(defaultDynamic);
  142. RegisterDynamic<Color4>();
  143. RegisterDynamic<Color3>();
  144. RegisterDynamic<Color>();
  145. RegisterDynamic<Vector4>();
  146. RegisterDynamic<Vector3>();
  147. RegisterDynamic<Vector2>();
  148. }
  149. /// <summary>
  150. /// Gets a tag value with the specified key.
  151. /// </summary>
  152. /// <param name="key">The tag key.</param>
  153. /// <returns>A tag value associated to a key</returns>
  154. public object GetTag(object key)
  155. {
  156. if (mapTag == null)
  157. return null;
  158. object value;
  159. mapTag.TryGetValue(key, out value);
  160. return value;
  161. }
  162. /// <summary>
  163. /// Determines whether a tag with a specified key is already stored.
  164. /// </summary>
  165. /// <param name="key">The key.</param>
  166. /// <returns><c>true</c> if a tag with a specified key is already stored; otherwise, <c>false</c>.</returns>
  167. public bool HasTag(object key)
  168. {
  169. if (mapTag == null)
  170. return false;
  171. return mapTag.ContainsKey(key);
  172. }
  173. /// <summary>
  174. /// Removes a tag with the specified key.
  175. /// </summary>
  176. /// <param name="key">The key.</param>
  177. public void RemoveTag(object key)
  178. {
  179. if (mapTag == null)
  180. return;
  181. mapTag.Remove(key);
  182. }
  183. /// <summary>
  184. /// Sets a tag value with the specified key.
  185. /// </summary>
  186. /// <param name="key">The key.</param>
  187. /// <param name="value">The value.</param>
  188. /// <returns></returns>
  189. public void SetTag(object key, object value)
  190. {
  191. if (mapTag == null)
  192. mapTag = new Dictionary<object, object>();
  193. // Always remove previous key before inserting new one
  194. mapTag.Remove(key);
  195. mapTag.Add(key, value);
  196. }
  197. /// <summary>
  198. /// Gets or sets the serialization mode.
  199. /// </summary>
  200. /// <value>The serialization mode.</value>
  201. public SerializerMode Mode
  202. {
  203. get { return mode; }
  204. set
  205. {
  206. mode = value;
  207. // Create Reader or writer
  208. if (Mode == SerializerMode.Read)
  209. {
  210. Reader = Reader ?? new BinaryReader(Stream);
  211. }
  212. else
  213. {
  214. Writer = Writer ?? new BinaryWriter(Stream);
  215. }
  216. }
  217. }
  218. /// <summary>
  219. /// Gets or sets the encoding used to serialized strings.
  220. /// </summary>
  221. /// <value>The encoding.</value>
  222. /// <exception cref="System.ArgumentNullException">When setting a null encoding</exception>
  223. public System.Text.Encoding Encoding
  224. {
  225. get { return encoding; }
  226. set {
  227. if (ReferenceEquals(value, null))
  228. throw new ArgumentNullException("value");
  229. if (!ReferenceEquals(encoding, value))
  230. {
  231. encoding = value;
  232. encoder = encoding.GetEncoder();
  233. decoder = encoding.GetDecoder();
  234. maxCharSize = encoding.GetMaxCharCount(LargeByteBufferSize);
  235. }
  236. }
  237. }
  238. /// <summary>
  239. /// Enables to serialize an object only once using object reference. Default is <strong>false</strong>.
  240. /// </summary>
  241. /// <value><c>true</c> if [allow null]; otherwise, <c>false</c>.</value>
  242. /// <exception cref="System.InvalidOperationException">If an invalid matching pair of true/false is detected.</exception>
  243. public bool AllowIdentity
  244. {
  245. get { return allowIdentityReferenceCount > 0; }
  246. set
  247. {
  248. allowIdentityReferenceCount += value ? 1 : -1;
  249. if (allowIdentityReferenceCount < 0)
  250. throw new InvalidOperationException("Invalid call to AllowIdentity. Must match true/false in pair.");
  251. }
  252. }
  253. /// <summary>
  254. /// Register a dynamic serializer for a particular type implementing the <see cref="IDataSerializable"/> interface and having the <see cref="DynamicSerializerAttribute"/>.
  255. /// </summary>
  256. /// <typeparam name="T">Type of the element to serialize.</typeparam>
  257. public void RegisterDynamic<T>() where T : IDataSerializable, new()
  258. {
  259. #if W8CORE
  260. var attribute = Utilities.GetCustomAttribute<DynamicSerializerAttribute>(typeof (T).GetTypeInfo());
  261. #else
  262. var attribute = Utilities.GetCustomAttribute<DynamicSerializerAttribute>(typeof (T));
  263. #endif
  264. if (attribute == null)
  265. throw new ArgumentException("Type T doesn't have DynamicSerializerAttribute", "T");
  266. RegisterDynamic<T>(attribute.Id);
  267. }
  268. /// <summary>
  269. /// Register a dynamic serializer for a particular type implementing the <see cref="IDataSerializable"/> interface.
  270. /// </summary>
  271. /// <typeparam name="T">Type of the element to serialize.</typeparam>
  272. /// <param name="id">The id to use for serializing T.</param>
  273. public void RegisterDynamic<T>(FourCC id) where T : IDataSerializable, new()
  274. {
  275. RegisterDynamic(GetDynamic<T>(id));
  276. }
  277. /// <summary>
  278. /// Register a dynamic array serializer for a particular type implementing the <see cref="IDataSerializable"/> interface.
  279. /// </summary>
  280. /// <typeparam name="T">Type of the element in the array.</typeparam>
  281. /// <param name="id">The id to use for serializing T[].</param>
  282. public void RegisterDynamicArray<T>(FourCC id) where T : IDataSerializable, new()
  283. {
  284. RegisterDynamic(GetDynamicArray<T>(id));
  285. }
  286. /// <summary>
  287. /// Register a dynamic List&lt;T&gt; serializer for a particular type implementing the <see cref="IDataSerializable"/> interface.
  288. /// </summary>
  289. /// <typeparam name="T">Type of the element in the List&lt;T&gt;.</typeparam>
  290. /// <param name="id">The id to use for serializing List&lt;T&gt;.</param>
  291. public void RegisterDynamicList<T>(FourCC id) where T : IDataSerializable, new()
  292. {
  293. RegisterDynamic(GetDynamicList<T>(id));
  294. }
  295. /// <summary>
  296. /// Register a dynamic serializer using an external action.
  297. /// </summary>
  298. /// <typeparam name="T">Type of the element to serialize.</typeparam>
  299. /// <param name="id">The id to use for serializing T.</param>
  300. /// <param name="serializer">The serializer.</param>
  301. public void RegisterDynamic<T>(FourCC id, SerializerAction serializer) where T : new()
  302. {
  303. var dynamicSerializer = new Dynamic {Id = id, Type = typeof (T), DynamicSerializer = serializer};
  304. dynamicSerializer.Reader = dynamicSerializer.DynamicReader<T>;
  305. dynamicSerializer.Writer = dynamicSerializer.DynamicWriter;
  306. RegisterDynamic(dynamicSerializer);
  307. }
  308. /// <summary>
  309. /// Begin to serialize a a new chunk.
  310. /// </summary>
  311. /// <param name="chunkId">The chunk id.</param>
  312. /// <exception cref="SharpDX.Serialization.InvalidChunkException">If the chuck to read is not the expecting chunk.</exception>
  313. /// <remarks>
  314. /// A Chunk is an identifiable portion of data that will serialized. Chunk are useful to encapsulate a variable
  315. /// data (and check for the presence of the chunk Id). Chunk are storing a 4 bytes identifier and the length of
  316. /// the chunk before reading/writing actual data.
  317. /// </remarks>
  318. public void BeginChunk(FourCC chunkId)
  319. {
  320. // Allocate new Chunk
  321. if (chunks[chunkCount] == null)
  322. {
  323. CurrentChunk = new Chunk();
  324. chunks[chunkCount] = CurrentChunk;
  325. }
  326. else
  327. {
  328. CurrentChunk = chunks[chunkCount];
  329. }
  330. // Go to next chunk
  331. chunkCount++;
  332. // Sets the current id
  333. CurrentChunk.Id = chunkId;
  334. // Create a new chunk
  335. if (Mode == SerializerMode.Write)
  336. CurrentChunk.ChunkIndexStart = Stream.Position;
  337. if (chunkCount >= chunks.Length)
  338. {
  339. var temp = new Chunk[chunks.Length * 2];
  340. Array.Copy(chunks, temp, chunks.Length);
  341. chunks = temp;
  342. }
  343. if (Mode == SerializerMode.Write)
  344. {
  345. // Write the chunkId to the current chunk
  346. Writer.Write((int) chunkId);
  347. // write temporary null size
  348. Writer.Write(0);
  349. }
  350. else
  351. {
  352. var chunkIdRead = Reader.ReadInt32();
  353. if (chunkIdRead != chunkId)
  354. throw new InvalidChunkException(chunkIdRead, chunkId);
  355. uint sizeOfChunk = (uint)Reader.ReadUInt32();
  356. CurrentChunk.ChunkIndexEnd = Stream.Position + sizeOfChunk;
  357. }
  358. }
  359. /// <summary>
  360. /// Ends a chunk.
  361. /// </summary>
  362. /// <exception cref="System.InvalidOperationException">If there EndChunk is called without a previous BeginChunk.</exception>
  363. /// <exception cref="System.IO.InvalidDataException">If the size of data read from the chunk is different from chunk size.</exception>
  364. public void EndChunk()
  365. {
  366. if (chunkCount <= 1)
  367. throw new InvalidOperationException("EndChunk() called without BeginChunk()");
  368. var previousChunk = CurrentChunk;
  369. chunkCount--;
  370. CurrentChunk = chunks[chunkCount - 1];
  371. if (Mode == SerializerMode.Write)
  372. {
  373. // Write the size of this chunk
  374. long currentPosition = Stream.Position;
  375. Stream.Position = previousChunk.ChunkIndexStart + 4;
  376. Writer.Write((uint)(currentPosition - Stream.Position - 4));
  377. Stream.Position = currentPosition;
  378. }
  379. else
  380. {
  381. if (previousChunk.ChunkIndexEnd != Stream.Position)
  382. throw new IOException(string.Format("Unexpected size when reading chunk [{0}]", CurrentChunk.Id));
  383. }
  384. }
  385. /// <summary>
  386. /// Deserialize a data from the underlying stream.
  387. /// </summary>
  388. /// <typeparam name="T">Type of the data to load.</typeparam>
  389. /// <returns>An instance of the loaded data.</returns>
  390. public T Load<T>() where T : IDataSerializable, new()
  391. {
  392. ResetStoredReference();
  393. Mode = SerializerMode.Read;
  394. T value = default(T);
  395. Serialize(ref value);
  396. return value;
  397. }
  398. /// <summary>
  399. /// Serializes the specified value to the underlying stream.
  400. /// </summary>
  401. /// <typeparam name="T">Type of the data to save.</typeparam>
  402. /// <param name="value">The value to save.</param>
  403. public void Save<T>(T value) where T : IDataSerializable, new()
  404. {
  405. ResetStoredReference();
  406. Mode = SerializerMode.Write;
  407. Serialize(ref value);
  408. Flush();
  409. }
  410. /// <summary>
  411. /// Flush the underlying <see cref="System.IO.Stream"/>
  412. /// </summary>
  413. public void Flush()
  414. {
  415. Writer.Flush();
  416. }
  417. /// <summary>
  418. /// Serializes a dynamic value that can be nullable.
  419. /// </summary>
  420. /// <typeparam name="T">Known type of the value to serialize. The known type is not the runtime type that will be actually serialized.</typeparam>
  421. /// <param name="value">The value to serialize based on its runtime type.</param>
  422. public void SerializeDynamic<T>(ref T value)
  423. {
  424. SerializeDynamic(ref value, SerializeFlags.Dynamic | SerializeFlags.Nullable);
  425. }
  426. /// <summary>
  427. /// Serializes a dynamic value.
  428. /// </summary>
  429. /// <typeparam name="T">Known type of the value to serialize. The known type is not the runtime type that will be actually serialized.</typeparam>
  430. /// <param name="value">The value to serialize based on its runtime type.</param>
  431. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  432. public void SerializeDynamic<T>(ref T value, SerializeFlags serializeFlags)
  433. {
  434. int storeObjectRef;
  435. if (SerializeIsNull(ref value, out storeObjectRef, serializeFlags | SerializeFlags.Dynamic))
  436. return;
  437. SerializeRawDynamic(ref value);
  438. }
  439. /// <summary>
  440. /// Serializes a static value implementing the <see cref="IDataSerializable"/> interface.
  441. /// </summary>
  442. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  443. /// <param name="value">The value to serialize</param>
  444. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  445. /// <remarks>
  446. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  447. /// </remarks>
  448. public void Serialize<T>(ref T value, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  449. {
  450. int storeObjectRef;
  451. if (SerializeIsNull(ref value, out storeObjectRef, serializeFlags))
  452. return;
  453. if (Mode == SerializerMode.Read)
  454. value = new T();
  455. // Store ObjectRef
  456. if (storeObjectRef >= 0) StoreObjectRef(value, storeObjectRef);
  457. value.Serialize(this);
  458. }
  459. /// <summary>
  460. /// Serializes a static value implementing the <see cref="IDataSerializable"/> interface. Unlike <see cref="Serialize{T}(ref T)"/>,
  461. /// this method doesn't allocate a new instance when reading but use the reference value.
  462. /// </summary>
  463. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  464. /// <param name="value">The value to serialize</param>
  465. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  466. /// <remarks>
  467. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  468. /// </remarks>
  469. public void SerializeWithNoInstance<T>(ref T value, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable
  470. {
  471. int storeObjectRef;
  472. if (SerializeIsNull(ref value, out storeObjectRef, serializeFlags))
  473. return;
  474. // Store ObjectRef
  475. if (storeObjectRef >= 0) StoreObjectRef(value, storeObjectRef);
  476. value.Serialize(this);
  477. }
  478. /// <summary>
  479. /// Serializes an enum value.
  480. /// </summary>
  481. /// <typeparam name="T">Type of the enum to serialize.</typeparam>
  482. /// <param name="value">The value to serialize</param>
  483. /// <exception cref="ArgumentException">If type T is not an enum.</exception>
  484. /// <remarks>
  485. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  486. /// </remarks>
  487. public unsafe void SerializeEnum<T>(ref T value) where T : struct, IComparable, IFormattable
  488. {
  489. if (!Utilities.IsEnum(typeof(T)))
  490. throw new ArgumentException("T generic parameter must be a valid enum", "value");
  491. var pValue = Interop.Fixed(ref value);
  492. switch (Utilities.SizeOf<T>())
  493. {
  494. case 1:
  495. {
  496. Serialize(ref *(byte*)pValue);
  497. break;
  498. }
  499. case 2:
  500. {
  501. Serialize(ref *(short*)pValue);
  502. break;
  503. }
  504. case 4:
  505. {
  506. Serialize(ref *(int*)pValue);
  507. break;
  508. }
  509. case 8:
  510. {
  511. Serialize(ref *(long*)pValue);
  512. break;
  513. }
  514. }
  515. }
  516. /// <summary>
  517. /// Serializes an array of primitives using serialization methods implemented by this instance for each item in the array.
  518. /// </summary>
  519. /// <typeparam name="T">Type of the primitive data to serialize.</typeparam>
  520. /// <param name="valueArray">An array of primitive value to serialize</param>
  521. /// <param name="serializer">The serializer to user to serialize the T values.</param>
  522. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  523. /// <remarks>
  524. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  525. /// </remarks>
  526. public void Serialize<T>(ref T[] valueArray, SerializerPrimitiveAction<T> serializer, SerializeFlags serializeFlags = SerializeFlags.Normal)
  527. {
  528. int storeObjectRef;
  529. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  530. return;
  531. if (Mode == SerializerMode.Write)
  532. {
  533. // Store ObjectRef
  534. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  535. WriteArrayLength((int)valueArray.Length);
  536. for (int i = 0; i < valueArray.Length; i++)
  537. serializer(ref valueArray[i]);
  538. }
  539. else
  540. {
  541. var count = ReadArrayLength();
  542. valueArray = new T[count];
  543. // Store ObjectRef
  544. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  545. for (int index = 0; index < count; index++)
  546. serializer(ref valueArray[index]);
  547. }
  548. }
  549. /// <summary>
  550. /// Serializes count elements in an array of primitives using serialization methods implemented by this instance for each item in the array.
  551. /// </summary>
  552. /// <typeparam name="T">Type of the primitive data to serialize.</typeparam>
  553. /// <param name="valueArray">An array of primitive value to serialize</param>
  554. /// <param name="count">Count elements to serialize. See remarks.</param>
  555. /// <param name="serializer">The serializer to user to serialize the T values.</param>
  556. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  557. /// <remarks>
  558. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.<br/>
  559. /// <strong>Caution</strong>: Also unlike the plain array version, the count is not serialized. This method is useful
  560. /// when we want to serialize the count of an array separately from the array.
  561. /// </remarks>
  562. public void Serialize<T>(ref T[] valueArray, int count, SerializerPrimitiveAction<T> serializer, SerializeFlags serializeFlags = SerializeFlags.Normal)
  563. {
  564. int storeObjectRef;
  565. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  566. return;
  567. if (Mode == SerializerMode.Write)
  568. {
  569. // Store ObjectRef
  570. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  571. for (int i = 0; i < count; i++)
  572. serializer(ref valueArray[i]);
  573. }
  574. else
  575. {
  576. valueArray = new T[count];
  577. // Store ObjectRef
  578. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  579. for (int index = 0; index < count; index++)
  580. serializer(ref valueArray[index]);
  581. }
  582. }
  583. /// <summary>
  584. /// Serializes an array of static values that are implementing the <see cref="IDataSerializable"/> interface.
  585. /// </summary>
  586. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  587. /// <param name="valueArray">An array of value to serialize</param>
  588. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  589. /// <remarks>
  590. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  591. /// </remarks>
  592. public void Serialize<T>(ref T[] valueArray, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  593. {
  594. int storeObjectRef;
  595. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  596. return;
  597. if (Mode == SerializerMode.Write)
  598. {
  599. // Store ObjectRef
  600. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  601. WriteArrayLength(valueArray.Length);
  602. for (int i = 0; i < valueArray.Length; i++)
  603. Serialize(ref valueArray[i], serializeFlags);
  604. }
  605. else
  606. {
  607. var count = ReadArrayLength();
  608. valueArray = new T[count];
  609. // Store ObjectRef
  610. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  611. for (int index = 0; index < count; index++)
  612. Serialize(ref valueArray[index], serializeFlags);
  613. }
  614. }
  615. /// <summary>
  616. /// Serializes an array of static values that are implementing the <see cref="IDataSerializable"/> interface.
  617. /// </summary>
  618. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  619. /// <param name="valueArray">An array of value to serialize</param>
  620. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  621. /// <remarks>
  622. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  623. /// </remarks>
  624. public void SerializeWithNoInstance<T>(ref T[] valueArray, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable
  625. {
  626. int storeObjectRef;
  627. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  628. return;
  629. if (Mode == SerializerMode.Write)
  630. {
  631. // Store ObjectRef
  632. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  633. WriteArrayLength(valueArray.Length);
  634. for (int i = 0; i < valueArray.Length; i++)
  635. SerializeWithNoInstance(ref valueArray[i], serializeFlags);
  636. }
  637. else
  638. {
  639. var count = ReadArrayLength();
  640. valueArray = new T[count];
  641. // Store ObjectRef
  642. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  643. for (int index = 0; index < count; index++)
  644. SerializeWithNoInstance(ref valueArray[index], serializeFlags);
  645. }
  646. }
  647. /// <summary>
  648. /// Serializes count elements in an array of static values that are implementing the <see cref="IDataSerializable"/> interface.
  649. /// </summary>
  650. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  651. /// <param name="valueArray">An array of value to serialize</param>
  652. /// <param name="count">Count elements to serialize. See remarks.</param>
  653. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  654. /// <remarks>
  655. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.<br/>
  656. /// <strong>Caution</strong>: Also unlike the plain array version, the count is not serialized. This method is useful
  657. /// when we want to serialize the count of an array separately from the array.
  658. /// </remarks>
  659. public void Serialize<T>(ref T[] valueArray, int count, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  660. {
  661. int storeObjectRef;
  662. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  663. return;
  664. if (Mode == SerializerMode.Write)
  665. {
  666. // Store ObjectRef
  667. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  668. for (int i = 0; i < count; i++)
  669. Serialize(ref valueArray[i], serializeFlags);
  670. }
  671. else
  672. {
  673. valueArray = new T[count];
  674. // Store ObjectRef
  675. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  676. for (int index = 0; index < count; index++)
  677. Serialize(ref valueArray[index], serializeFlags);
  678. }
  679. }
  680. /// <summary>
  681. /// Serializes an array of bytes.
  682. /// </summary>
  683. /// <param name="valueArray">An array of bytes to serialize</param>
  684. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  685. /// <remarks>
  686. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  687. /// </remarks>
  688. public void Serialize(ref byte[] valueArray, SerializeFlags serializeFlags = SerializeFlags.Normal)
  689. {
  690. int storeObjectRef;
  691. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  692. return;
  693. if (Mode == SerializerMode.Write)
  694. {
  695. // Store ObjectRef
  696. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  697. WriteArrayLength(valueArray.Length);
  698. Writer.Write(valueArray);
  699. }
  700. else
  701. {
  702. int count = ReadArrayLength();
  703. valueArray = new byte[count];
  704. // Store ObjectRef
  705. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  706. Reader.Read(valueArray, 0, count);
  707. }
  708. }
  709. /// <summary>
  710. /// Serializes an array of bytes.
  711. /// </summary>
  712. /// <param name="valueArray">An array of bytes to serialize</param>
  713. /// <param name="count">Count elements to serialize. See remarks.</param>
  714. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  715. /// <remarks>
  716. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.<br/>
  717. /// <strong>Caution</strong>: Also unlike the plain array version, the count is not serialized. This method is useful
  718. /// when we want to serialize the count of an array separately from the array.
  719. /// </remarks>
  720. public void Serialize(ref byte[] valueArray, int count, SerializeFlags serializeFlags = SerializeFlags.Normal)
  721. {
  722. int storeObjectRef;
  723. if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags))
  724. return;
  725. if (Mode == SerializerMode.Write)
  726. {
  727. // Store ObjectRef
  728. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  729. Writer.Write(valueArray, 0, count);
  730. }
  731. else
  732. {
  733. valueArray = new byte[count];
  734. // Store ObjectRef
  735. if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef);
  736. Reader.Read(valueArray, 0, count);
  737. }
  738. }
  739. /// <summary>
  740. /// Serializes a list of static values that are implementing the <see cref="IDataSerializable"/> interface.
  741. /// </summary>
  742. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  743. /// <param name="valueList">A list of value to serialize</param>
  744. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  745. /// <remarks>
  746. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  747. /// </remarks>
  748. public void Serialize<T>(ref List<T> valueList, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  749. {
  750. int storeObjectRef;
  751. if (SerializeIsNull(ref valueList, out storeObjectRef, serializeFlags))
  752. return;
  753. if (Mode == SerializerMode.Write)
  754. {
  755. // Store ObjectRef
  756. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  757. WriteArrayLength(valueList.Count);
  758. foreach (var value in valueList)
  759. {
  760. T localValue = value;
  761. Serialize(ref localValue);
  762. }
  763. }
  764. else
  765. {
  766. var count = ReadArrayLength();
  767. valueList = new List<T>(count);
  768. // Store ObjectRef
  769. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  770. for (int index = 0; index < count; index++)
  771. {
  772. var value = default(T);
  773. Serialize(ref value);
  774. valueList.Add(value);
  775. }
  776. }
  777. }
  778. /// <summary>
  779. /// Serializes a list of static values that are implementing the <see cref="IDataSerializable"/> interface.
  780. /// </summary>
  781. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  782. /// <param name="valueList">A list of value to serialize</param>
  783. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  784. /// <remarks>
  785. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  786. /// </remarks>
  787. public void SerializeThis<T>(List<T> valueList, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  788. {
  789. if (Mode == SerializerMode.Write)
  790. {
  791. WriteArrayLength(valueList.Count);
  792. foreach (var value in valueList)
  793. {
  794. T localValue = value;
  795. Serialize(ref localValue);
  796. }
  797. }
  798. else
  799. {
  800. var count = ReadArrayLength();
  801. for (int index = 0; index < count; index++)
  802. {
  803. var value = default(T);
  804. Serialize(ref value);
  805. valueList.Add(value);
  806. }
  807. }
  808. }
  809. /// <summary>
  810. /// Serializes a list of primitive values using a specific serializer method from this instance.
  811. /// </summary>
  812. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  813. /// <param name="valueList">A list of value to serialize</param>
  814. /// <param name="serializerMethod">A method of this instance to serialize the primitive T type</param>
  815. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  816. /// <remarks>
  817. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  818. /// </remarks>
  819. public void Serialize<T>(ref List<T> valueList, SerializerPrimitiveAction<T> serializerMethod, SerializeFlags serializeFlags = SerializeFlags.Normal)
  820. {
  821. int storeObjectRef;
  822. if (SerializeIsNull(ref valueList, out storeObjectRef, serializeFlags))
  823. return;
  824. if (Mode == SerializerMode.Write)
  825. {
  826. // Store ObjectRef
  827. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  828. WriteArrayLength(valueList.Count);
  829. foreach (var value in valueList)
  830. {
  831. T localValue = value;
  832. serializerMethod(ref localValue);
  833. }
  834. }
  835. else
  836. {
  837. var count = ReadArrayLength();
  838. EnsureList(ref valueList, count);
  839. // Store ObjectRef
  840. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  841. for (int i = 0; i < count; i++)
  842. {
  843. var localValue = default(T);
  844. serializerMethod(ref localValue);
  845. valueList.Add(localValue);
  846. }
  847. }
  848. }
  849. /// <summary>
  850. /// Serializes count elements from a list of static values that are implementing the <see cref="IDataSerializable"/> interface.
  851. /// </summary>
  852. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  853. /// <param name="valueList">A list of value to serialize</param>
  854. /// <param name="count">Count elements to serialize. See remarks.</param>
  855. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  856. /// <remarks>
  857. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.<br/>
  858. /// <strong>Caution</strong>: Also unlike the plain array version, the count is not serialized. This method is useful
  859. /// when we want to serialize the count of an array separately from the array.
  860. /// </remarks>
  861. public void Serialize<T>(ref List<T> valueList, int count, SerializeFlags serializeFlags = SerializeFlags.Normal) where T : IDataSerializable, new()
  862. {
  863. int storeObjectRef;
  864. if (SerializeIsNull(ref valueList, out storeObjectRef, serializeFlags))
  865. return;
  866. if (Mode == SerializerMode.Write)
  867. {
  868. // Store ObjectRef
  869. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  870. for (int i = 0; i < count; i++)
  871. {
  872. T localValue = valueList[i];
  873. Serialize(ref localValue, serializeFlags);
  874. }
  875. }
  876. else
  877. {
  878. EnsureList(ref valueList, count);
  879. // Store ObjectRef
  880. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  881. for (int index = 0; index < count; index++)
  882. {
  883. var value = default(T);
  884. Serialize(ref value, serializeFlags);
  885. valueList.Add(value);
  886. }
  887. }
  888. }
  889. /// <summary>
  890. /// Serializes count elements from a list of primitive values using a specific serializer method from this instance.
  891. /// </summary>
  892. /// <typeparam name="T">Type of the data to serialize.</typeparam>
  893. /// <param name="valueList">A list of value to serialize</param>
  894. /// <param name="serializerMethod">A method of this instance to serialize the primitive T type</param>
  895. /// <param name="count">Count elements to serialize. See remarks.</param>
  896. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  897. /// <remarks>
  898. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.<br/>
  899. /// <strong>Caution</strong>: Also unlike the plain array version, the count is not serialized. This method is useful
  900. /// when we want to serialize the count of an array separately from the array.
  901. /// </remarks>
  902. public void Serialize<T>(ref List<T> valueList, int count, SerializerPrimitiveAction<T> serializerMethod, SerializeFlags serializeFlags = SerializeFlags.Normal)
  903. {
  904. int storeObjectRef;
  905. if (SerializeIsNull(ref valueList, out storeObjectRef, serializeFlags))
  906. return;
  907. if (Mode == SerializerMode.Write)
  908. {
  909. // Store ObjectRef
  910. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  911. for (int i = 0; i < count; i++)
  912. {
  913. T localValue = valueList[i];
  914. serializerMethod(ref localValue);
  915. }
  916. }
  917. else
  918. {
  919. EnsureList(ref valueList, count);
  920. // Store ObjectRef
  921. if (storeObjectRef >= 0) StoreObjectRef(valueList, storeObjectRef);
  922. for (int i = 0; i < count; i++)
  923. {
  924. var localValue = default(T);
  925. serializerMethod(ref localValue);
  926. valueList.Add(localValue);
  927. }
  928. }
  929. }
  930. private void EnsureList<T>(ref List<T> valueList, int count)
  931. {
  932. // If there is a list provided, use it in place instead of allocating a new one
  933. if (valueList != null)
  934. {
  935. valueList.Clear();
  936. if (valueList.Capacity < count)
  937. {
  938. valueList.Capacity = count;
  939. }
  940. }
  941. else
  942. {
  943. valueList = new List<T>(count);
  944. }
  945. }
  946. /// <summary>
  947. /// Serializes a dictionary of key/values that are both implementing the <see cref="IDataSerializable"/> interface.
  948. /// </summary>
  949. /// <typeparam name="TKey">Type of key to serialize.</typeparam>
  950. /// <typeparam name="TValue">Type of value to serialize.</typeparam>
  951. /// <param name="dictionary">A dictionary to serialize</param>
  952. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  953. /// <remarks>
  954. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  955. /// </remarks>
  956. public void Serialize<TKey, TValue>(ref Dictionary<TKey, TValue> dictionary, SerializeFlags serializeFlags = SerializeFlags.Normal)
  957. where TKey : IDataSerializable, new()
  958. where TValue : IDataSerializable, new()
  959. {
  960. int storeObjectRef;
  961. if (SerializeIsNull(ref dictionary, out storeObjectRef, serializeFlags))
  962. return;
  963. if (Mode == SerializerMode.Write)
  964. {
  965. // Store ObjectRef
  966. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  967. WriteArrayLength(dictionary.Count);
  968. foreach (var value in dictionary)
  969. {
  970. TKey localKey = value.Key;
  971. TValue localValue = value.Value;
  972. localKey.Serialize(this);
  973. localValue.Serialize(this);
  974. }
  975. }
  976. else
  977. {
  978. var count = ReadArrayLength();
  979. dictionary = new Dictionary<TKey, TValue>(count);
  980. // Store ObjectRef
  981. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  982. for (int i = 0; i < count; i++)
  983. {
  984. TKey localKey = default(TKey);
  985. TValue localValue = default(TValue);
  986. localKey.Serialize(this);
  987. localValue.Serialize(this);
  988. dictionary.Add(localKey, localValue);
  989. }
  990. }
  991. }
  992. /// <summary>
  993. /// Serializes a dictionary of key/values.
  994. /// </summary>
  995. /// <typeparam name="TKey">Type of key to serialize that is implementing the <see cref="IDataSerializable"/> interface.</typeparam>
  996. /// <typeparam name="TValue">Type of primitive value with its associated serializer.</typeparam>
  997. /// <param name="dictionary">A dictionary to serialize</param>
  998. /// <param name="valueSerializer">Serializer used for the TValue.</param>
  999. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  1000. /// <remarks>
  1001. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1002. /// </remarks>
  1003. public void Serialize<TKey, TValue>(ref Dictionary<TKey, TValue> dictionary, SerializerPrimitiveAction<TValue> valueSerializer, SerializeFlags serializeFlags = SerializeFlags.Normal) where TKey : IDataSerializable, new()
  1004. {
  1005. int storeObjectRef;
  1006. if (SerializeIsNull(ref dictionary, out storeObjectRef, serializeFlags))
  1007. return;
  1008. if (Mode == SerializerMode.Write)
  1009. {
  1010. // Store ObjectRef
  1011. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1012. WriteArrayLength(dictionary.Count);
  1013. foreach (var value in dictionary)
  1014. {
  1015. TKey localKey = value.Key;
  1016. TValue localValue = value.Value;
  1017. localKey.Serialize(this);
  1018. valueSerializer(ref localValue);
  1019. }
  1020. }
  1021. else
  1022. {
  1023. var count = ReadArrayLength();
  1024. dictionary = new Dictionary<TKey, TValue>(count);
  1025. // Store ObjectRef
  1026. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1027. for (int i = 0; i < count; i++)
  1028. {
  1029. TKey localKey = default(TKey);
  1030. TValue localValue = default(TValue);
  1031. localKey.Serialize(this);
  1032. valueSerializer(ref localValue);
  1033. dictionary.Add(localKey, localValue);
  1034. }
  1035. }
  1036. }
  1037. /// <summary>
  1038. /// Serializes a dictionary of key/values.
  1039. /// </summary>
  1040. /// <typeparam name="TKey">Type of primitive value with its associated serializer.</typeparam>
  1041. /// <typeparam name="TValue">Type of value to serialize that is implementing the <see cref="IDataSerializable"/> interface.</typeparam>
  1042. /// <param name="dictionary">A dictionary to serialize</param>
  1043. /// <param name="keySerializer">Serializer used for the TKey.</param>
  1044. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  1045. /// <remarks>
  1046. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1047. /// </remarks>
  1048. public void Serialize<TKey, TValue>(ref Dictionary<TKey, TValue> dictionary, SerializerPrimitiveAction<TKey> keySerializer, SerializeFlags serializeFlags = SerializeFlags.Normal) where TValue : IDataSerializable, new()
  1049. {
  1050. int storeObjectRef;
  1051. if (SerializeIsNull(ref dictionary, out storeObjectRef, serializeFlags))
  1052. return;
  1053. if (Mode == SerializerMode.Write)
  1054. {
  1055. // Store ObjectRef
  1056. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1057. WriteArrayLength(dictionary.Count);
  1058. foreach (var value in dictionary)
  1059. {
  1060. TKey localKey = value.Key;
  1061. TValue localValue = value.Value;
  1062. keySerializer(ref localKey);
  1063. localValue.Serialize(this);
  1064. }
  1065. }
  1066. else
  1067. {
  1068. var count = ReadArrayLength();
  1069. dictionary = new Dictionary<TKey, TValue>(count);
  1070. // Store ObjectRef
  1071. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1072. for (int i = 0; i < count; i++)
  1073. {
  1074. TKey localKey = default(TKey);
  1075. TValue localValue = default(TValue);
  1076. keySerializer(ref localKey);
  1077. localValue.Serialize(this);
  1078. dictionary.Add(localKey, localValue);
  1079. }
  1080. }
  1081. }
  1082. /// <summary>
  1083. /// Serializes a dictionary of key/values.
  1084. /// </summary>
  1085. /// <typeparam name="TKey">Type of primitive key with its associated serializer.</typeparam>
  1086. /// <typeparam name="TValue">Type of primitive value with its associated serializer.</typeparam>
  1087. /// <param name="dictionary">A dictionary to serialize</param>
  1088. /// <param name="keySerializer">Serializer used for the TKey.</param>
  1089. /// <param name="valueSerializer">Serializer used for the TValue.</param>
  1090. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  1091. /// <remarks>
  1092. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1093. /// </remarks>
  1094. public void Serialize<TKey, TValue>(ref Dictionary<TKey, TValue> dictionary, SerializerPrimitiveAction<TKey> keySerializer, SerializerPrimitiveAction<TValue> valueSerializer, SerializeFlags serializeFlags = SerializeFlags.Normal)
  1095. {
  1096. int storeObjectRef;
  1097. if (SerializeIsNull(ref dictionary, out storeObjectRef, serializeFlags))
  1098. return;
  1099. if (Mode == SerializerMode.Write)
  1100. {
  1101. // Store ObjectRef
  1102. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1103. WriteArrayLength(dictionary.Count);
  1104. foreach (var value in dictionary)
  1105. {
  1106. TKey localKey = value.Key;
  1107. TValue localValue = value.Value;
  1108. keySerializer(ref localKey);
  1109. valueSerializer(ref localValue);
  1110. }
  1111. }
  1112. else
  1113. {
  1114. var count = ReadArrayLength();
  1115. dictionary = new Dictionary<TKey, TValue>(count);
  1116. // Store ObjectRef
  1117. if (storeObjectRef >= 0) StoreObjectRef(dictionary, storeObjectRef);
  1118. for (int i = 0; i < count; i++)
  1119. {
  1120. TKey localKey = default(TKey);
  1121. TValue localValue = default(TValue);
  1122. keySerializer(ref localKey);
  1123. valueSerializer(ref localValue);
  1124. dictionary.Add(localKey, localValue);
  1125. }
  1126. }
  1127. }
  1128. /// <summary>
  1129. /// Serializes a single <strong>string</strong> value.
  1130. /// </summary>
  1131. /// <param name="value">The value to serialize</param>
  1132. /// <remarks>
  1133. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1134. /// This string is serialized with the current <see cref="Encoding"/> set on this instance.
  1135. /// </remarks>
  1136. public void Serialize(ref string value)
  1137. {
  1138. Serialize(ref value, false);
  1139. }
  1140. /// <summary>
  1141. /// Serializes a single <strong>string</strong> value.
  1142. /// </summary>
  1143. /// <param name="value">The value to serialize</param>
  1144. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  1145. /// <remarks>
  1146. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1147. /// This string is serialized with the current <see cref="Encoding"/> set on this instance.
  1148. /// </remarks>
  1149. public void Serialize(ref string value, SerializeFlags serializeFlags)
  1150. {
  1151. Serialize(ref value, false, serializeFlags);
  1152. }
  1153. /// <summary>
  1154. /// Serializes a single <strong>string</strong> value.
  1155. /// </summary>
  1156. /// <param name="value">The value to serialize</param>
  1157. /// <param name="writeNullTerminatedString">Write a null byte at the end of the string.</param>
  1158. /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param>
  1159. /// <remarks>
  1160. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1161. /// This string is serialized with the current <see cref="Encoding"/> set on this instance.
  1162. /// </remarks>
  1163. public void Serialize(ref string value, bool writeNullTerminatedString, SerializeFlags serializeFlags = SerializeFlags.Normal)
  1164. {
  1165. int storeObjectRef = -1;
  1166. // If len < 0, then we need to check for null/identity.
  1167. if (SerializeIsNull(ref value, out storeObjectRef, serializeFlags))
  1168. return;
  1169. if (Mode == SerializerMode.Write)
  1170. {
  1171. WriteString(value, writeNullTerminatedString, -1);
  1172. }
  1173. else
  1174. {
  1175. value = ReadString(writeNullTerminatedString, -1);
  1176. }
  1177. // Store ObjectRef
  1178. if (storeObjectRef >= 0) StoreObjectRef(value, storeObjectRef);
  1179. }
  1180. /// <summary>
  1181. /// Serializes a single fixed length <strong>string</strong> value.
  1182. /// </summary>
  1183. /// <param name="value">The value to serialize</param>
  1184. /// <param name="len">Read/write a specific number of characters.</param>
  1185. /// <remarks>
  1186. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1187. /// This string is serialized with the current <see cref="Encoding"/> set on this instance.
  1188. /// </remarks>
  1189. public void Serialize(ref string value, int len)
  1190. {
  1191. if (Mode == SerializerMode.Write)
  1192. {
  1193. WriteString(value, false, len);
  1194. }
  1195. else
  1196. {
  1197. value = ReadString(false, len);
  1198. }
  1199. }
  1200. /// <summary>
  1201. /// Serializes a single <strong>boolean</strong> value.
  1202. /// </summary>
  1203. /// <param name="value">The value to serialize</param>
  1204. /// <remarks>
  1205. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1206. /// </remarks>
  1207. public void Serialize(ref bool value)
  1208. {
  1209. if (Mode == SerializerMode.Write)
  1210. {
  1211. Writer.Write(value);
  1212. }
  1213. else
  1214. {
  1215. value = Reader.ReadBoolean();
  1216. }
  1217. }
  1218. /// <summary>
  1219. /// Serializes a single <strong>byte</strong> value.
  1220. /// </summary>
  1221. /// <param name="value">The value to serialize</param>
  1222. /// <remarks>
  1223. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1224. /// </remarks>
  1225. public void Serialize(ref byte value)
  1226. {
  1227. if (Mode == SerializerMode.Write)
  1228. {
  1229. Writer.Write(value);
  1230. }
  1231. else
  1232. {
  1233. value = Reader.ReadByte();
  1234. }
  1235. }
  1236. /// <summary>
  1237. /// Serializes a single <strong>sbyte</strong> value.
  1238. /// </summary>
  1239. /// <param name="value">The value to serialize</param>
  1240. /// <remarks>
  1241. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1242. /// </remarks>
  1243. public void Serialize(ref sbyte value)
  1244. {
  1245. if (Mode == SerializerMode.Write)
  1246. {
  1247. Writer.Write(value);
  1248. }
  1249. else
  1250. {
  1251. value = Reader.ReadSByte();
  1252. }
  1253. }
  1254. /// <summary>
  1255. /// Serializes a single <strong>short</strong> value.
  1256. /// </summary>
  1257. /// <param name="value">The value to serialize</param>
  1258. /// <remarks>
  1259. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1260. /// </remarks>
  1261. public void Serialize(ref short value)
  1262. {
  1263. if (Mode == SerializerMode.Write)
  1264. {
  1265. Writer.Write(value);
  1266. }
  1267. else
  1268. {
  1269. value = Reader.ReadInt16();
  1270. }
  1271. }
  1272. /// <summary>
  1273. /// Serializes a single <strong>ushort</strong> value.
  1274. /// </summary>
  1275. /// <param name="value">The value to serialize</param>
  1276. /// <remarks>
  1277. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1278. /// </remarks>
  1279. public void Serialize(ref ushort value)
  1280. {
  1281. if (Mode == SerializerMode.Write)
  1282. {
  1283. Writer.Write(value);
  1284. }
  1285. else
  1286. {
  1287. value = Reader.ReadUInt16();
  1288. }
  1289. }
  1290. /// <summary>
  1291. /// Serializes a single <strong>int</strong> value.
  1292. /// </summary>
  1293. /// <param name="value">The value to serialize</param>
  1294. /// <remarks>
  1295. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1296. /// </remarks>
  1297. public void Serialize(ref int value)
  1298. {
  1299. if (Mode == SerializerMode.Write)
  1300. {
  1301. Writer.Write(value);
  1302. }
  1303. else
  1304. {
  1305. value = Reader.ReadInt32();
  1306. }
  1307. }
  1308. /// <summary>
  1309. /// Serializes a single <strong>int</strong> as a packed value (from 1 byte to 5 byte. if value &lt; 128, then 1 byte...etc.)
  1310. /// </summary>
  1311. /// <param name="value">The value to serialize</param>
  1312. /// <remarks>
  1313. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1314. /// </remarks>
  1315. public void SerializePackedInt(ref int value)
  1316. {
  1317. if (Mode == SerializerMode.Write)
  1318. {
  1319. Write7BitEncodedInt(value);
  1320. }
  1321. else
  1322. {
  1323. value = Read7BitEncodedInt();
  1324. }
  1325. }
  1326. /// <summary>
  1327. /// Serializes a memory region.
  1328. /// </summary>
  1329. /// <param name="dataRegion">The pointer to an unmanaged memory region. For read operation, this pointer must be allocated by the caller.</param>
  1330. /// <exception cref="System.IO.EndOfStreamException">If the end of stream was reached before reading all the bytes.</exception>
  1331. /// <remarks>Note that depending on the serialization <see cref="Mode" />, this method reads or writes the value.
  1332. /// This method doesn't serialize the sizeInBytes of the region, so the size must be serialized separately.
  1333. /// </remarks>
  1334. public void SerializeMemoryRegion(DataPointer dataRegion)
  1335. {
  1336. SerializeMemoryRegion(dataRegion.Pointer, dataRegion.Size);
  1337. }
  1338. /// <summary>
  1339. /// Serializes a memory region.
  1340. /// </summary>
  1341. /// <param name="dataPointer">The data pointer. For read operation, this pointer must be allocated by the caller.</param>
  1342. /// <param name="sizeInBytes">The size in bytes. See remarks.</param>
  1343. /// <exception cref="System.IO.EndOfStreamException">If the end of stream was reached before reading all the bytes.</exception>
  1344. /// <remarks>Note that depending on the serialization <see cref="Mode" />, this method reads or writes the value.
  1345. /// This method doesn't serialize the sizeInBytes of the region, so the size must be serialized separately.
  1346. /// </remarks>
  1347. public unsafe void SerializeMemoryRegion(IntPtr dataPointer, int sizeInBytes)
  1348. {
  1349. // Provides optimized path for special streams
  1350. var fileStream = Stream as NativeFileStream;
  1351. if (fileStream != null)
  1352. {
  1353. if (Mode == SerializerMode.Write)
  1354. {
  1355. fileStream.Write(dataPointer, 0, sizeInBytes);
  1356. }
  1357. else
  1358. {
  1359. fileStream.Read(dataPointer, 0, sizeInBytes);
  1360. }
  1361. }
  1362. else if (Stream is DataStream)
  1363. {
  1364. if (Mode == SerializerMode.Write)
  1365. {
  1366. ((DataStream)Stream).Write(dataPointer, 0, sizeInBytes);
  1367. }
  1368. else
  1369. {
  1370. ((DataStream)Stream).Read(dataPointer, 0, sizeInBytes);
  1371. }
  1372. }
  1373. else
  1374. {
  1375. const int internalBufferSize = 32768;
  1376. if (largeByteBuffer == null)
  1377. largeByteBuffer = new byte[internalBufferSize];
  1378. if (largeByteBuffer.Length < internalBufferSize)
  1379. largeByteBuffer = new byte[internalBufferSize];
  1380. if (Mode == SerializerMode.Write)
  1381. {
  1382. var remainingSize = sizeInBytes;
  1383. while (remainingSize > 0)
  1384. {
  1385. var maxSize = remainingSize < largeByteBuffer.Length ? remainingSize : largeByteBuffer.Length;
  1386. Utilities.Read(dataPointer, largeByteBuffer, 0, maxSize);
  1387. Stream.Write(largeByteBuffer, 0, maxSize);
  1388. dataPointer = (IntPtr) ((byte*) dataPointer + maxSize);
  1389. remainingSize -= maxSize;
  1390. }
  1391. }
  1392. else
  1393. {
  1394. var remainingSize = sizeInBytes;
  1395. while (remainingSize > 0)
  1396. {
  1397. var maxSize = remainingSize < largeByteBuffer.Length ? remainingSize : largeByteBuffer.Length;
  1398. if (Stream.Read(largeByteBuffer, 0, maxSize) != maxSize)
  1399. throw new EndOfStreamException();
  1400. Utilities.Write(dataPointer, largeByteBuffer, 0, maxSize);
  1401. dataPointer = (IntPtr)((byte*)dataPointer + maxSize);
  1402. remainingSize -= maxSize;
  1403. }
  1404. }
  1405. }
  1406. }
  1407. /// <summary>
  1408. /// Serializes a single <strong>uint</strong> value.
  1409. /// </summary>
  1410. /// <param name="value">The value to serialize</param>
  1411. /// <remarks>
  1412. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1413. /// </remarks>
  1414. public void Serialize(ref uint value)
  1415. {
  1416. if (Mode == SerializerMode.Write)
  1417. {
  1418. Writer.Write(value);
  1419. }
  1420. else
  1421. {
  1422. value = Reader.ReadUInt32();
  1423. }
  1424. }
  1425. /// <summary>
  1426. /// Serializes a single <strong>long</strong> value.
  1427. /// </summary>
  1428. /// <param name="value">The value to serialize</param>
  1429. /// <remarks>
  1430. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1431. /// </remarks>
  1432. public void Serialize(ref long value)
  1433. {
  1434. if (Mode == SerializerMode.Write)
  1435. {
  1436. Writer.Write(value);
  1437. }
  1438. else
  1439. {
  1440. value = Reader.ReadInt64();
  1441. }
  1442. }
  1443. /// <summary>
  1444. /// Serializes a single <strong>ulong</strong> value.
  1445. /// </summary>
  1446. /// <param name="value">The value to serialize</param>
  1447. /// <remarks>
  1448. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1449. /// </remarks>
  1450. public void Serialize(ref ulong value)
  1451. {
  1452. if (Mode == SerializerMode.Write)
  1453. {
  1454. Writer.Write(value);
  1455. }
  1456. else
  1457. {
  1458. value = Reader.ReadUInt64();
  1459. }
  1460. }
  1461. /// <summary>
  1462. /// Serializes a single <strong>char</strong> value.
  1463. /// </summary>
  1464. /// <param name="value">The value to serialize</param>
  1465. /// <remarks>
  1466. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1467. /// </remarks>
  1468. public void Serialize(ref char value)
  1469. {
  1470. if (Mode == SerializerMode.Write)
  1471. {
  1472. Writer.Write(value);
  1473. }
  1474. else
  1475. {
  1476. value = Reader.ReadChar();
  1477. }
  1478. }
  1479. /// <summary>
  1480. /// Serializes a single <strong>float</strong> value.
  1481. /// </summary>
  1482. /// <param name="value">The value to serialize</param>
  1483. /// <remarks>
  1484. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1485. /// </remarks>
  1486. public void Serialize(ref float value)
  1487. {
  1488. if (Mode == SerializerMode.Write)
  1489. {
  1490. Writer.Write(value);
  1491. }
  1492. else
  1493. {
  1494. value = Reader.ReadSingle();
  1495. }
  1496. }
  1497. /// <summary>
  1498. /// Serializes a single <strong>double</strong> value.
  1499. /// </summary>
  1500. /// <param name="value">The value to serialize</param>
  1501. /// <remarks>
  1502. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1503. /// </remarks>
  1504. public void Serialize(ref double value)
  1505. {
  1506. if (Mode == SerializerMode.Write)
  1507. {
  1508. Writer.Write(value);
  1509. }
  1510. else
  1511. {
  1512. value = Reader.ReadDouble();
  1513. }
  1514. }
  1515. /// <summary>
  1516. /// Serializes a single <strong>DateTime</strong> value.
  1517. /// </summary>
  1518. /// <param name="value">The value to serialize</param>
  1519. /// <remarks>
  1520. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1521. /// </remarks>
  1522. public void Serialize(ref DateTime value)
  1523. {
  1524. if (Mode == SerializerMode.Write)
  1525. {
  1526. Writer.Write(value.ToBinary());
  1527. }
  1528. else
  1529. {
  1530. value = new DateTime(Reader.ReadInt64());
  1531. }
  1532. }
  1533. /// <summary>
  1534. /// Serializes a single <strong>Guid</strong> value.
  1535. /// </summary>
  1536. /// <param name="value">The value to serialize</param>
  1537. /// <remarks>
  1538. /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value.
  1539. /// </remarks>
  1540. public void Serialize(ref Guid value)
  1541. {
  1542. if (Mode == SerializerMode.Write)
  1543. {
  1544. Writer.Write(value.ToByteArray());
  1545. }
  1546. else
  1547. {
  1548. value = new Guid(Reader.ReadBytes(16));
  1549. }
  1550. }
  1551. private bool SerializeIsNull<T>(ref T value, out int storeObjectReference, SerializeFlags flags)
  1552. {
  1553. storeObjectReference = -1;
  1554. // If value type, no null possible
  1555. if (Utilities.IsValueType(typeof(T)))
  1556. return false;
  1557. bool isNullValue = ReferenceEquals(value, null);
  1558. if ((flags & SerializeFlags.Nullable) != 0 || allowIdentityReferenceCount > 0)
  1559. {
  1560. // Handle write
  1561. if (Mode == SerializerMode.Write)
  1562. {
  1563. // Handle reference
  1564. if (!isNullValue && allowIdentityReferenceCount > 0 && (flags & SerializeFlags.Dynamic) == 0)
  1565. {
  1566. int position;
  1567. if (objectToPosition.TryGetValue(value, out position))
  1568. {
  1569. Writer.Write((byte)2);
  1570. Write7BitEncodedInt(position);
  1571. return true;
  1572. }
  1573. // Register reference
  1574. objectToPosition.Add(value, (int)Stream.Position);
  1575. }
  1576. Writer.Write((byte)(isNullValue ? 0 : 1));
  1577. return isNullValue;
  1578. }
  1579. else
  1580. {
  1581. // Handle read
  1582. value = default(T);
  1583. int objectPosition = (int)Stream.Position;
  1584. int objectReferenceHeader = Reader.ReadByte();
  1585. switch (objectReferenceHeader)
  1586. {
  1587. case 1:
  1588. {
  1589. if (allowIdentityReferenceCount > 0 && (flags & SerializeFlags.Dynamic) == 0)
  1590. storeObjectReference = objectPosition;
  1591. }
  1592. break;
  1593. case 2:
  1594. {
  1595. if (allowIdentityReferenceCount == 0)
  1596. throw new InvalidOperationException("Can't read serialized reference when SerializeReference is off");
  1597. // Read object position from stream
  1598. objectPosition = Read7BitEncodedInt();
  1599. object localValue;
  1600. if (!positionToObject.TryGetValue(objectPosition, out localValue))
  1601. throw new InvalidOperationException(string.Format("Can't find serialized reference at position [{0}]", objectPosition));
  1602. // Set Object Reference
  1603. value = (T) localValue;
  1604. // Set it as null
  1605. objectReferenceHeader = 0;
  1606. }
  1607. break;
  1608. }
  1609. return objectReferenceHeader == 0;
  1610. }
  1611. }
  1612. // Null is not allowed
  1613. if (isNullValue && Mode == SerializerMode.Write)
  1614. {
  1615. throw new ArgumentNullException("value");
  1616. }
  1617. return false;
  1618. }
  1619. private void SerializeRawDynamic<T>(ref T value, bool noDynamic = false)
  1620. {
  1621. if (Mode == SerializerMode.Write)
  1622. {
  1623. var type = (noDynamic) ? typeof (T) : value.GetType();
  1624. Dynamic dyn;
  1625. if (!dynamicMapToFourCC.TryGetValue(type, out dyn))
  1626. throw new IOException(string.Format("Type [{0}] is not registered as dynamic", type));
  1627. // Write the id of the object
  1628. if (!noDynamic)
  1629. Writer.Write((int) dyn.Id);
  1630. dyn.Writer(value, this);
  1631. }
  1632. else
  1633. {
  1634. // Gets the id for this dynamic
  1635. Dynamic dyn;
  1636. if (noDynamic)
  1637. {
  1638. var type = typeof (T);
  1639. if (!dynamicMapToFourCC.TryGetValue(type, out dyn))
  1640. throw new IOException(string.Format("Type [{0}] is not registered as dynamic", type));
  1641. }
  1642. else
  1643. {
  1644. var id = (FourCC) Reader.ReadInt32();
  1645. if (!dynamicMapToType.TryGetValue(id, out dyn))
  1646. throw new IOException(string.Format("Type [{0}] is not registered as dynamic", id));
  1647. }
  1648. value = (T) dyn.Reader(this);
  1649. }
  1650. }
  1651. private void RegisterDynamic(Dynamic dynamic)
  1652. {
  1653. dynamicMapToFourCC.Add(dynamic.Type, dynamic);
  1654. dynamicMapToType.Add(dynamic.Id, dynamic);
  1655. }
  1656. #region Primitive Array Readers
  1657. private static object ReaderIntArray(BinarySerializer serializer)
  1658. {
  1659. int[] value = null;
  1660. serializer.Serialize(ref value, serializer.Serialize);
  1661. return value;
  1662. }
  1663. private static object ReaderUIntArray(BinarySerializer serializer)
  1664. {
  1665. uint[] value = null;
  1666. serializer.Serialize(ref value, serializer.Serialize);
  1667. return value;
  1668. }
  1669. private static object ReaderShortArray(BinarySerializer serializer)
  1670. {
  1671. short[] value = null;
  1672. serializer.Serialize(ref value, serializer.Serialize);
  1673. return value;
  1674. }
  1675. private static object ReaderUShortArray(BinarySerializer serializer)
  1676. {
  1677. ushort[] value = null;
  1678. serializer.Serialize(ref value, serializer.Serialize);
  1679. return value;
  1680. }
  1681. private static object ReaderLongArray(BinarySerializer serializer)
  1682. {
  1683. long[] value = null;
  1684. serializer.Serialize(ref value, serializer.Serialize);
  1685. return value;
  1686. }
  1687. private static object ReaderULongArray(BinarySerializer serializer)
  1688. {
  1689. ulong[] value = null;
  1690. serializer.Serialize(ref value, serializer.Serialize);
  1691. return value;
  1692. }
  1693. private static object ReaderBoolArray(BinarySerializer serializer)
  1694. {
  1695. bool[] value = null;
  1696. serializer.Serialize(ref value, serializer.Serialize);
  1697. return value;
  1698. }
  1699. private static object ReaderFloatArray(BinarySerializer serializer)
  1700. {
  1701. float[] value = null;
  1702. serializer.Serialize(ref value, serializer.Serialize);
  1703. return value;
  1704. }
  1705. private static object ReaderDoubleArray(BinarySerializer serializer)
  1706. {
  1707. double[] value = null;
  1708. serializer.Serialize(ref value, serializer.Serialize);
  1709. return value;
  1710. }
  1711. private static object ReaderDateTimeArray(BinarySerializer serializer)
  1712. {
  1713. DateTime[] value = null;
  1714. serializer.Serialize(ref value, serializer.Serialize);
  1715. return value;
  1716. }
  1717. private static object ReaderGuidArray(BinarySerializer serializer)
  1718. {
  1719. Guid[] value = null;
  1720. serializer.Serialize(ref value, serializer.Serialize);
  1721. return value;
  1722. }
  1723. private static object ReaderObjectArray(BinarySerializer serializer)
  1724. {
  1725. object[] value = null;
  1726. serializer.Serialize(ref value, serializer.SerializeDynamic);
  1727. return value;
  1728. }
  1729. private static object ReaderCharArray(BinarySerializer serializer)
  1730. {
  1731. char[] value = null;
  1732. serializer.Serialize(ref value, serializer.Serialize);
  1733. return value;
  1734. }
  1735. private static object ReaderStringArray(BinarySerializer serializer)
  1736. {
  1737. string[] value = null;
  1738. serializer.Serialize(ref value, serializer.Serialize);
  1739. return value;
  1740. }
  1741. private static object ReaderByteArray(BinarySerializer serializer)
  1742. {
  1743. byte[] value = null;
  1744. serializer.Serialize(ref value);
  1745. return value;
  1746. }
  1747. private static object ReaderSByteArray(BinarySerializer serializer)
  1748. {
  1749. sbyte[] values = null;
  1750. serializer.Serialize(ref values, serializer.Serialize);
  1751. return values;
  1752. }
  1753. #endregion
  1754. #region Primitive Array Writer
  1755. private static void WriterIntArray(object value, BinarySerializer serializer)
  1756. {
  1757. var valueTyped = (int[]) value;
  1758. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1759. }
  1760. private static void WriterUIntArray(object value, BinarySerializer serializer)
  1761. {
  1762. var valueTyped = (uint[]) value;
  1763. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1764. }
  1765. private static void WriterShortArray(object value, BinarySerializer serializer)
  1766. {
  1767. var valueTyped = (short[]) value;
  1768. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1769. }
  1770. private static void WriterUShortArray(object value, BinarySerializer serializer)
  1771. {
  1772. var valueTyped = (ushort[]) value;
  1773. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1774. }
  1775. private static void WriterLongArray(object value, BinarySerializer serializer)
  1776. {
  1777. var valueTyped = (long[]) value;
  1778. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1779. }
  1780. private static void WriterULongArray(object value, BinarySerializer serializer)
  1781. {
  1782. var valueTyped = (ulong[]) value;
  1783. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1784. }
  1785. private static void WriterSByteArray(object value, BinarySerializer serializer)
  1786. {
  1787. var valueTyped = (sbyte[]) value;
  1788. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1789. }
  1790. private static void WriterStringArray(object value, BinarySerializer serializer)
  1791. {
  1792. var valueTyped = (string[]) value;
  1793. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1794. }
  1795. private static void WriterCharArray(object value, BinarySerializer serializer)
  1796. {
  1797. var valueTyped = (char[]) value;
  1798. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1799. }
  1800. private static void WriterBoolArray(object value, BinarySerializer serializer)
  1801. {
  1802. var valueTyped = (bool[]) value;
  1803. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1804. }
  1805. private static void WriterFloatArray(object value, BinarySerializer serializer)
  1806. {
  1807. var valueTyped = (float[]) value;
  1808. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1809. }
  1810. private static void WriterDoubleArray(object value, BinarySerializer serializer)
  1811. {
  1812. var valueTyped = (double[]) value;
  1813. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1814. }
  1815. private static void WriterDateTimeArray(object value, BinarySerializer serializer)
  1816. {
  1817. var valueTyped = (DateTime[]) value;
  1818. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1819. }
  1820. private static void WriterGuidArray(object value, BinarySerializer serializer)
  1821. {
  1822. var valueTyped = (Guid[]) value;
  1823. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1824. }
  1825. private static void WriterObjectArray(object value, BinarySerializer serializer)
  1826. {
  1827. var valueTyped = (object[])value;
  1828. serializer.Serialize(ref valueTyped, serializer.SerializeDynamic);
  1829. }
  1830. private static void WriterByteArray(object value, BinarySerializer serializer)
  1831. {
  1832. var valueArray = (byte[]) value;
  1833. serializer.Serialize(ref valueArray);
  1834. }
  1835. #endregion
  1836. #region Primitive List Readers
  1837. private static object ReaderIntList(BinarySerializer serializer)
  1838. {
  1839. List<int> value = null;
  1840. serializer.Serialize(ref value, serializer.Serialize);
  1841. return value;
  1842. }
  1843. private static object ReaderUIntList(BinarySerializer serializer)
  1844. {
  1845. List<uint> value = null;
  1846. serializer.Serialize(ref value, serializer.Serialize);
  1847. return value;
  1848. }
  1849. private static object ReaderShortList(BinarySerializer serializer)
  1850. {
  1851. List<short> value = null;
  1852. serializer.Serialize(ref value, serializer.Serialize);
  1853. return value;
  1854. }
  1855. private static object ReaderUShortList(BinarySerializer serializer)
  1856. {
  1857. List<ushort> value = null;
  1858. serializer.Serialize(ref value, serializer.Serialize);
  1859. return value;
  1860. }
  1861. private static object ReaderLongList(BinarySerializer serializer)
  1862. {
  1863. List<long> value = null;
  1864. serializer.Serialize(ref value, serializer.Serialize);
  1865. return value;
  1866. }
  1867. private static object ReaderULongList(BinarySerializer serializer)
  1868. {
  1869. List<ulong> value = null;
  1870. serializer.Serialize(ref value, serializer.Serialize);
  1871. return value;
  1872. }
  1873. private static object ReaderBoolList(BinarySerializer serializer)
  1874. {
  1875. List<bool> value = null;
  1876. serializer.Serialize(ref value, serializer.Serialize);
  1877. return value;
  1878. }
  1879. private static object ReaderFloatList(BinarySerializer serializer)
  1880. {
  1881. List<float> value = null;
  1882. serializer.Serialize(ref value, serializer.Serialize);
  1883. return value;
  1884. }
  1885. private static object ReaderDoubleList(BinarySerializer serializer)
  1886. {
  1887. List<double> value = null;
  1888. serializer.Serialize(ref value, serializer.Serialize);
  1889. return value;
  1890. }
  1891. private static object ReaderDateTimeList(BinarySerializer serializer)
  1892. {
  1893. List<DateTime> value = null;
  1894. serializer.Serialize(ref value, serializer.Serialize);
  1895. return value;
  1896. }
  1897. private static object ReaderGuidList(BinarySerializer serializer)
  1898. {
  1899. List<Guid> value = null;
  1900. serializer.Serialize(ref value, serializer.Serialize);
  1901. return value;
  1902. }
  1903. private static object ReaderObjectList(BinarySerializer serializer)
  1904. {
  1905. List<object> value = null;
  1906. serializer.Serialize(ref value, serializer.SerializeDynamic);
  1907. return value;
  1908. }
  1909. private static object ReaderCharList(BinarySerializer serializer)
  1910. {
  1911. List<char> value = null;
  1912. serializer.Serialize(ref value, serializer.Serialize);
  1913. return value;
  1914. }
  1915. private static object ReaderStringList(BinarySerializer serializer)
  1916. {
  1917. List<string> value = null;
  1918. serializer.Serialize(ref value, serializer.Serialize);
  1919. return value;
  1920. }
  1921. private static object ReaderByteList(BinarySerializer serializer)
  1922. {
  1923. List<byte> value = null;
  1924. serializer.Serialize(ref value, serializer.Serialize);
  1925. return value;
  1926. }
  1927. private static object ReaderSByteList(BinarySerializer serializer)
  1928. {
  1929. List<sbyte> value = null;
  1930. serializer.Serialize(ref value, serializer.Serialize);
  1931. return value;
  1932. }
  1933. #endregion
  1934. #region Primitive List Writers
  1935. private static void WriterIntList(object value, BinarySerializer serializer)
  1936. {
  1937. var valueTyped = (List<int>) value;
  1938. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1939. }
  1940. private static void WriterUIntList(object value, BinarySerializer serializer)
  1941. {
  1942. var valueTyped = (List<uint>) value;
  1943. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1944. }
  1945. private static void WriterShortList(object value, BinarySerializer serializer)
  1946. {
  1947. var valueTyped = (List<short>) value;
  1948. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1949. }
  1950. private static void WriterUShortList(object value, BinarySerializer serializer)
  1951. {
  1952. var valueTyped = (List<ushort>) value;
  1953. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1954. }
  1955. private static void WriterLongList(object value, BinarySerializer serializer)
  1956. {
  1957. var valueTyped = (List<long>) value;
  1958. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1959. }
  1960. private static void WriterULongList(object value, BinarySerializer serializer)
  1961. {
  1962. var valueTyped = (List<ulong>) value;
  1963. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1964. }
  1965. private static void WriterSByteList(object value, BinarySerializer serializer)
  1966. {
  1967. var valueTyped = (List<sbyte>) value;
  1968. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1969. }
  1970. private static void WriterStringList(object value, BinarySerializer serializer)
  1971. {
  1972. var valueTyped = (List<string>) value;
  1973. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1974. }
  1975. private static void WriterCharList(object value, BinarySerializer serializer)
  1976. {
  1977. var valueTyped = (List<char>) value;
  1978. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1979. }
  1980. private static void WriterBoolList(object value, BinarySerializer serializer)
  1981. {
  1982. var valueTyped = (List<bool>) value;
  1983. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1984. }
  1985. private static void WriterFloatList(object value, BinarySerializer serializer)
  1986. {
  1987. var valueTyped = (List<float>) value;
  1988. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1989. }
  1990. private static void WriterDoubleList(object value, BinarySerializer serializer)
  1991. {
  1992. var valueTyped = (List<double>) value;
  1993. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1994. }
  1995. private static void WriterDateTimeList(object value, BinarySerializer serializer)
  1996. {
  1997. var valueTyped = (List<DateTime>) value;
  1998. serializer.Serialize(ref valueTyped, serializer.Serialize);
  1999. }
  2000. private static void WriterGuidList(object value, BinarySerializer serializer)
  2001. {
  2002. var valueTyped = (List<Guid>) value;
  2003. serializer.Serialize(ref valueTyped, serializer.Serialize);
  2004. }
  2005. private static void WriterObjectList(object value, BinarySerializer serializer)
  2006. {
  2007. var valueTyped = (List<object>)value;
  2008. serializer.Serialize(ref valueTyped, serializer.SerializeDynamic);
  2009. }
  2010. private static void WriterByteList(object value, BinarySerializer serializer)
  2011. {
  2012. var valueTyped = (List<byte>) value;
  2013. serializer.Serialize(ref valueTyped, serializer.Serialize);
  2014. }
  2015. #endregion
  2016. #region Primitive Readers
  2017. private static object ReaderInt(BinarySerializer serializer)
  2018. {
  2019. return serializer.Reader.ReadInt32();
  2020. }
  2021. private static object ReaderUInt(BinarySerializer serializer)
  2022. {
  2023. return serializer.Reader.ReadUInt32();
  2024. }
  2025. private static object ReaderShort(BinarySerializer serializer)
  2026. {
  2027. return serializer.Reader.ReadInt16();
  2028. }
  2029. private static object ReaderUShort(BinarySerializer serializer)
  2030. {
  2031. return serializer.Reader.ReadUInt16();
  2032. }
  2033. private static object ReaderLong(BinarySerializer serializer)
  2034. {
  2035. return serializer.Reader.ReadInt64();
  2036. }
  2037. private static object ReaderULong(BinarySerializer serializer)
  2038. {
  2039. return serializer.Reader.ReadUInt64();
  2040. }
  2041. private static object ReaderBool(BinarySerializer serializer)
  2042. {
  2043. return serializer.Reader.ReadBoolean();
  2044. }
  2045. private static object ReaderByte(BinarySerializer serializer)
  2046. {
  2047. return serializer.Reader.ReadByte();
  2048. }
  2049. private static object ReaderSByte(BinarySerializer serializer)
  2050. {
  2051. return serializer.Reader.ReadSByte();
  2052. }
  2053. private static object ReaderString(BinarySerializer serializer)
  2054. {
  2055. var value = (string) null;
  2056. serializer.Serialize(ref value);
  2057. return value;
  2058. }
  2059. private static object ReaderFloat(BinarySerializer serializer)
  2060. {
  2061. return serializer.Reader.ReadSingle();
  2062. }
  2063. private static object ReaderDouble(BinarySerializer serializer)
  2064. {
  2065. return serializer.Reader.ReadDouble();
  2066. }
  2067. private static object ReaderChar(BinarySerializer serializer)
  2068. {
  2069. return serializer.Reader.ReadChar();
  2070. }
  2071. private static object ReaderDateTime(BinarySerializer serializer)
  2072. {
  2073. return new DateTime(serializer.Reader.ReadInt64());
  2074. }
  2075. private static object ReaderGuid(BinarySerializer serializer)
  2076. {
  2077. return new Guid(serializer.Reader.ReadBytes(16));
  2078. }
  2079. #endregion
  2080. #region Primitive Writers
  2081. private static void WriterInt(object value, BinarySerializer serializer)
  2082. {
  2083. serializer.Writer.Write((int) value);
  2084. }
  2085. private static void WriterUInt(object value, BinarySerializer serializer)
  2086. {
  2087. serializer.Writer.Write((uint) value);
  2088. }
  2089. private static void WriterShort(object value, BinarySerializer serializer)
  2090. {
  2091. serializer.Writer.Write((short) value);
  2092. }
  2093. private static void WriterUShort(object value, BinarySerializer serializer)
  2094. {
  2095. serializer.Writer.Write((ushort) value);
  2096. }
  2097. private static void WriterLong(object value, BinarySerializer serializer)
  2098. {
  2099. serializer.Writer.Write((long) value);
  2100. }
  2101. private static void WriterULong(object value, BinarySerializer serializer)
  2102. {
  2103. serializer.Writer.Write((ulong) value);
  2104. }
  2105. private static void WriterByte(object value, BinarySerializer serializer)
  2106. {
  2107. serializer.Writer.Write((byte) value);
  2108. }
  2109. private static void WriterSByte(object value, BinarySerializer serializer)
  2110. {
  2111. serializer.Writer.Write((sbyte) value);
  2112. }
  2113. private static void WriterString(object value, BinarySerializer serializer)
  2114. {
  2115. var str = (string) value;
  2116. serializer.Serialize(ref str);
  2117. }
  2118. private static void WriterChar(object value, BinarySerializer serializer)
  2119. {
  2120. serializer.Writer.Write((char) value);
  2121. }
  2122. private static void WriterBool(object value, BinarySerializer serializer)
  2123. {
  2124. serializer.Writer.Write((bool) value);
  2125. }
  2126. private static void WriterFloat(object value, BinarySerializer serializer)
  2127. {
  2128. serializer.Writer.Write((float) value);
  2129. }
  2130. private static void WriterDouble(object value, BinarySerializer serializer)
  2131. {
  2132. serializer.Writer.Write((double) value);
  2133. }
  2134. private static void WriterDateTime(object value, BinarySerializer serializer)
  2135. {
  2136. serializer.Writer.Write(((DateTime) value).ToBinary());
  2137. }
  2138. private static void WriterGuid(object value, BinarySerializer serializer)
  2139. {
  2140. serializer.Writer.Write(((Guid) value).ToByteArray());
  2141. }
  2142. #endregion
  2143. #region IDataSerializable Reader and Writer (+ Array and List)
  2144. private static object ReaderDataSerializer<T>(BinarySerializer serializer) where T : IDataSerializable, new()
  2145. {
  2146. var value = default(T);
  2147. serializer.Serialize(ref value);
  2148. return value;
  2149. }
  2150. private static void WriterDataSerializer<T>(object value, BinarySerializer serializer) where T : IDataSerializable, new()
  2151. {
  2152. var valueTyped = (T)value;
  2153. serializer.Serialize(ref valueTyped);
  2154. }
  2155. private static object ReaderDataSerializerArray<T>(BinarySerializer serializer) where T : IDataSerializable, new()
  2156. {
  2157. var value = (T[]) null;
  2158. serializer.Serialize(ref value);
  2159. return value;
  2160. }
  2161. private static void WriterDataSerializerArray<T>(object value, BinarySerializer serializer) where T : IDataSerializable, new()
  2162. {
  2163. var valueList = (T[]) value;
  2164. serializer.Serialize(ref valueList);
  2165. }
  2166. private static object ReaderDataSerializerList<T>(BinarySerializer serializer) where T : IDataSerializable, new()
  2167. {
  2168. var value = (List<T>) null;
  2169. serializer.Serialize(ref value);
  2170. return value;
  2171. }
  2172. private static void WriterDataSerializerList<T>(object value, BinarySerializer serializer) where T : IDataSerializable, new()
  2173. {
  2174. var valueList = (List<T>) value;
  2175. serializer.Serialize(ref valueList);
  2176. }
  2177. #endregion
  2178. private static readonly List<Dynamic> DefaultDynamics = new List<Dynamic>()
  2179. {
  2180. new Dynamic {Id = 0, Type = typeof (int), Reader = ReaderInt, Writer = WriterInt},
  2181. new Dynamic {Id = 1, Type = typeof (uint), Reader = ReaderUInt, Writer = WriterUInt},
  2182. new Dynamic {Id = 2, Type = typeof (short), Reader = ReaderShort, Writer = WriterShort},
  2183. new Dynamic {Id = 3, Type = typeof (ushort), Reader = ReaderUShort, Writer = WriterUShort},
  2184. new Dynamic {Id = 4, Type = typeof (long), Reader = ReaderLong, Writer = WriterLong},
  2185. new Dynamic {Id = 5, Type = typeof (ulong), Reader = ReaderULong, Writer = WriterULong},
  2186. new Dynamic {Id = 6, Type = typeof (byte), Reader = ReaderByte, Writer = WriterByte},
  2187. new Dynamic {Id = 7, Type = typeof (sbyte), Reader = ReaderSByte, Writer = WriterSByte},
  2188. new Dynamic {Id = 8, Type = typeof (bool), Reader = ReaderBool, Writer = WriterBool},
  2189. new Dynamic {Id = 9, Type = typeof (float), Reader = ReaderFloat, Writer = WriterFloat},
  2190. new Dynamic {Id = 10, Type = typeof (double), Reader = ReaderDouble, Writer = WriterDouble},
  2191. new Dynamic {Id = 11, Type = typeof (string), Reader = ReaderString, Writer = WriterString},
  2192. new Dynamic {Id = 12, Type = typeof (char), Reader = ReaderChar, Writer = WriterChar},
  2193. new Dynamic {Id = 13, Type = typeof (DateTime), Reader = ReaderDateTime, Writer = WriterDateTime},
  2194. new Dynamic {Id = 14, Type = typeof (Guid), Reader = ReaderGuid, Writer = WriterGuid},
  2195. new Dynamic {Id = 30, Type = typeof (int[]), Reader = ReaderIntArray, Writer = WriterIntArray},
  2196. new Dynamic {Id = 31, Type = typeof (uint[]), Reader = ReaderUIntArray, Writer = WriterUIntArray},
  2197. new Dynamic {Id = 32, Type = typeof (short[]), Reader = ReaderShortArray, Writer = WriterShortArray},
  2198. new Dynamic {Id = 33, Type = typeof (ushort[]), Reader = ReaderUShortArray, Writer = WriterUShortArray},
  2199. new Dynamic {Id = 34, Type = typeof (long[]), Reader = ReaderLongArray, Writer = WriterLongArray},
  2200. new Dynamic {Id = 35, Type = typeof (ulong[]), Reader = ReaderULongArray, Writer = WriterULongArray},
  2201. new Dynamic {Id = 36, Type = typeof (byte[]), Reader = ReaderByteArray, Writer = WriterByteArray},
  2202. new Dynamic {Id = 37, Type = typeof (sbyte[]), Reader = ReaderSByteArray, Writer = WriterSByteArray},
  2203. new Dynamic {Id = 38, Type = typeof (bool[]), Reader = ReaderBoolArray, Writer = WriterBoolArray},
  2204. new Dynamic {Id = 39, Type = typeof (float[]), Reader = ReaderFloatArray, Writer = WriterFloatArray},
  2205. new Dynamic {Id = 40, Type = typeof (double[]), Reader = ReaderDoubleArray, Writer = WriterDoubleArray},
  2206. new Dynamic {Id = 41, Type = typeof (string[]), Reader = ReaderStringArray, Writer = WriterStringArray},
  2207. new Dynamic {Id = 42, Type = typeof (char[]), Reader = ReaderCharArray, Writer = WriterCharArray},
  2208. new Dynamic {Id = 43, Type = typeof (DateTime[]), Reader = ReaderDateTimeArray, Writer = WriterDateTimeArray},
  2209. new Dynamic {Id = 44, Type = typeof (Guid[]), Reader = ReaderGuidArray, Writer = WriterGuidArray},
  2210. new Dynamic {Id = 45, Type = typeof (object[]), Reader = ReaderObjectArray, Writer = WriterObjectArray},
  2211. new Dynamic {Id = 60, Type = typeof (List<int>), Reader = ReaderIntList, Writer = WriterIntList},
  2212. new Dynamic {Id = 61, Type = typeof (List<uint>), Reader = ReaderUIntList, Writer = WriterUIntList},
  2213. new Dynamic {Id = 62, Type = typeof (List<short>), Reader = ReaderShortList, Writer = WriterShortList},
  2214. new Dynamic {Id = 63, Type = typeof (List<ushort>), Reader = ReaderUShortList, Writer = WriterUShortList},
  2215. new Dynamic {Id = 64, Type = typeof (List<long>), Reader = ReaderLongList, Writer = WriterLongList},
  2216. new Dynamic {Id = 65, Type = typeof (List<ulong>), Reader = ReaderULongList, Writer = WriterULongList},
  2217. new Dynamic {Id = 66, Type = typeof (List<byte>), Reader = ReaderByteList, Writer = WriterByteList},
  2218. new Dynamic {Id = 67, Type = typeof (List<sbyte>), Reader = ReaderSByteList, Writer = WriterSByteList},
  2219. new Dynamic {Id = 68, Type = typeof (List<bool>), Reader = ReaderBoolList, Writer = WriterBoolList},
  2220. new Dynamic {Id = 69, Type = typeof (List<float>), Reader = ReaderFloatList, Writer = WriterFloatList},
  2221. new Dynamic {Id = 70, Type = typeof (List<double>), Reader = ReaderDoubleList, Writer = WriterDoubleList},
  2222. new Dynamic {Id = 71, Type = typeof (List<string>), Reader = ReaderStringList, Writer = WriterStringList},
  2223. new Dynamic {Id = 72, Type = typeof (List<char>), Reader = ReaderCharList, Writer = WriterCharList},
  2224. new Dynamic {Id = 73, Type = typeof (List<DateTime>), Reader = ReaderDateTimeList, Writer = WriterDateTimeList},
  2225. new Dynamic {Id = 74, Type = typeof (List<Guid>), Reader = ReaderGuidList, Writer = WriterGuidList},
  2226. new Dynamic {Id = 75, Type = typeof (List<object>), Reader = ReaderObjectList, Writer = WriterObjectList},
  2227. };
  2228. private Chunk CurrentChunk
  2229. {
  2230. get { return currentChunk; }
  2231. set { currentChunk = value; }
  2232. }
  2233. private class Chunk
  2234. {
  2235. public FourCC Id;
  2236. public long ChunkIndexStart;
  2237. public long ChunkIndexEnd;
  2238. }
  2239. private void StoreObjectRef(object value, int position)
  2240. {
  2241. objectToPosition.Add(value, position);
  2242. positionToObject.Add(position, value);
  2243. }
  2244. private void ResetStoredReference()
  2245. {
  2246. positionToObject.Clear();
  2247. objectToPosition.Clear();
  2248. }
  2249. private String ReadString(bool readNullTerminatedString, int stringLength)
  2250. {
  2251. int currPos = 0;
  2252. int n;
  2253. int readLength;
  2254. int charsRead;
  2255. if (largeByteBuffer == null)
  2256. largeByteBuffer = new byte[LargeByteBufferSize];
  2257. if (largeCharBuffer == null)
  2258. largeCharBuffer = new char[maxCharSize];
  2259. var result = String.Empty;
  2260. if (readNullTerminatedString)
  2261. {
  2262. byte nextByte;
  2263. while ((nextByte = Reader.ReadByte()) != 0)
  2264. {
  2265. // If index i greater the buffer, then reallocate the buffer.
  2266. if (currPos == largeByteBuffer.Length)
  2267. {
  2268. var temp = new byte[largeByteBuffer.Length * 2];
  2269. Array.Copy(largeByteBuffer, 0, temp, 0, largeByteBuffer.Length);
  2270. largeByteBuffer = temp;
  2271. }
  2272. largeByteBuffer[currPos++] = nextByte;
  2273. }
  2274. // Reallocate chars.
  2275. var maxCharCount = encoding.GetMaxCharCount(currPos);
  2276. if (maxCharCount > largeCharBuffer.Length)
  2277. largeCharBuffer = new char[maxCharCount];
  2278. int charRead = decoder.GetChars(largeByteBuffer, 0, currPos, largeCharBuffer, 0);
  2279. result = new string(largeCharBuffer, 0, charRead);
  2280. }
  2281. else
  2282. {
  2283. // Length of the string in bytes, not chars
  2284. if (stringLength < 0)
  2285. {
  2286. stringLength = ReadArrayLength();
  2287. if (stringLength < 0)
  2288. throw new IOException(string.Format("Invalid string length ({0})", stringLength));
  2289. }
  2290. if (stringLength > 0)
  2291. {
  2292. StringBuilder sb = null;
  2293. do
  2294. {
  2295. readLength = ((stringLength - currPos) > LargeByteBufferSize) ? LargeByteBufferSize : (stringLength - currPos);
  2296. n = Stream.Read(largeByteBuffer, 0, readLength);
  2297. if (n == 0)
  2298. throw new EndOfStreamException();
  2299. charsRead = decoder.GetChars(largeByteBuffer, 0, n, largeCharBuffer, 0);
  2300. if (currPos == 0 && n == stringLength)
  2301. return new String(largeCharBuffer, 0, charsRead);
  2302. if (sb == null)
  2303. sb = new StringBuilder(stringLength); // Actual string length in chars may be smaller.
  2304. sb.Append(largeCharBuffer, 0, charsRead);
  2305. currPos += n;
  2306. } while (currPos < stringLength);
  2307. result = sb.ToString();
  2308. }
  2309. }
  2310. return result;
  2311. }
  2312. private unsafe void WriteString(String value, bool writeNullTerminated, int len)
  2313. {
  2314. if (value == null)
  2315. throw new ArgumentNullException("value");
  2316. // If len == -1, then we are serializing the length
  2317. if (len < 0)
  2318. {
  2319. len = encoding.GetByteCount(value);
  2320. // If null terminated string, don't output the length of the string before string data.
  2321. if (!writeNullTerminated)
  2322. {
  2323. WriteArrayLength(len);
  2324. }
  2325. }
  2326. else
  2327. {
  2328. if (value.Length != len)
  2329. throw new ArgumentException(string.Format("length of string to serialized ({0}) != fixed length ({1})", value.Length, len));
  2330. // Cannot use null terminated string with fixed length
  2331. if (writeNullTerminated)
  2332. throw new ArgumentException("Cannot use null terminated string and fixed length");
  2333. }
  2334. if (largeByteBuffer == null)
  2335. {
  2336. largeByteBuffer = new byte[LargeByteBufferSize];
  2337. maxChars = LargeByteBufferSize / encoding.GetMaxByteCount(1);
  2338. }
  2339. if (len <= LargeByteBufferSize)
  2340. {
  2341. //BCLDebug.Assert(len == _encoding.GetBytes(chars, 0, chars.Length, largeByteBuffer, 0), "encoding's GetByteCount & GetBytes gave different answers! encoding type: "+_encoding.GetType().Name);
  2342. encoding.GetBytes(value, 0, value.Length, largeByteBuffer, 0);
  2343. Stream.Write(largeByteBuffer, 0, len);
  2344. }
  2345. else
  2346. {
  2347. // Aggressively try to not allocate memory in this loop for
  2348. // runtime performance reasons. Use an Encoder to write out
  2349. // the string correctly (handling surrogates crossing buffer
  2350. // boundaries properly).
  2351. int charStart = 0;
  2352. int numLeft = value.Length;
  2353. while (numLeft > 0)
  2354. {
  2355. // Figure out how many chars to process this round.
  2356. int charCount = (numLeft > maxChars) ? maxChars : numLeft;
  2357. int byteLen;
  2358. #if W8CORE
  2359. // This is inefficient, but .NET 4.5 Core profile doesn't give us the choice.
  2360. var charArray = value.ToCharArray();
  2361. byteLen = encoder.GetBytes(charArray, charStart, charCount, largeByteBuffer, 0, charCount == numLeft);
  2362. #else
  2363. fixed (char* pChars = value)
  2364. {
  2365. fixed (byte* pBytes = largeByteBuffer)
  2366. {
  2367. byteLen = encoder.GetBytes(pChars + charStart, charCount, pBytes, LargeByteBufferSize, charCount == numLeft);
  2368. }
  2369. }
  2370. #endif
  2371. Stream.Write(largeByteBuffer, 0, byteLen);
  2372. charStart += charCount;
  2373. numLeft -= charCount;
  2374. }
  2375. }
  2376. // Write a null terminated string
  2377. if (writeNullTerminated)
  2378. Stream.WriteByte(0);
  2379. }
  2380. protected int ReadArrayLength()
  2381. {
  2382. switch (ArrayLengthType)
  2383. {
  2384. case ArrayLengthType.Dynamic:
  2385. return Read7BitEncodedInt();
  2386. case ArrayLengthType.Byte:
  2387. return Reader.ReadByte();
  2388. case ArrayLengthType.UShort:
  2389. return Reader.ReadUInt16();
  2390. }
  2391. return Reader.ReadInt32();
  2392. }
  2393. protected void WriteArrayLength(int value)
  2394. {
  2395. switch (ArrayLengthType)
  2396. {
  2397. case ArrayLengthType.Dynamic:
  2398. Write7BitEncodedInt(value);
  2399. break;
  2400. case ArrayLengthType.Byte:
  2401. if (value > 255) throw new NotSupportedException(string.Format("Cannot serialize array length [{0}], larger then ArrayLengthType [{1}]", value, 255));
  2402. Writer.Write((byte)value);
  2403. break;
  2404. case ArrayLengthType.UShort:
  2405. if (value > 65535) throw new NotSupportedException(string.Format("Cannot serialize array length [{0}], larger then ArrayLengthType [{1}]", value, 65535));
  2406. Writer.Write((ushort)value);
  2407. break;
  2408. case ArrayLengthType.Int:
  2409. if (value < 0) throw new NotSupportedException(string.Format("Cannot serialize array length [{0}], larger then ArrayLengthType [{1}]", value, 0x7FFFFFF));
  2410. Writer.Write(value);
  2411. break;
  2412. }
  2413. }
  2414. protected int Read7BitEncodedInt()
  2415. {
  2416. // Read out an Int32 7 bits at a time. The high bit
  2417. // of the byte when on means to continue reading more bytes.
  2418. int count = 0;
  2419. int shift = 0;
  2420. byte b;
  2421. do
  2422. {
  2423. // Check for a corrupted stream. Read a max of 5 bytes.
  2424. // In a future version, add a DataFormatException.
  2425. if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7
  2426. throw new FormatException("Bad string length. 7bit Int32 format");
  2427. // ReadByte handles end of stream cases for us.
  2428. b = Reader.ReadByte();
  2429. count |= (b & 0x7F) << shift;
  2430. shift += 7;
  2431. } while ((b & 0x80) != 0);
  2432. return count;
  2433. }
  2434. protected void Write7BitEncodedInt(int value)
  2435. {
  2436. // Write out an int 7 bits at a time. The high bit of the byte,
  2437. // when on, tells reader to continue reading more bytes.
  2438. uint v = (uint)value; // support negative numbers
  2439. while (v >= 0x80)
  2440. {
  2441. Writer.Write((byte)(v | 0x80));
  2442. v >>= 7;
  2443. }
  2444. Writer.Write((byte)v);
  2445. }
  2446. private static Dynamic GetDynamic<T>(FourCC id) where T : IDataSerializable, new()
  2447. {
  2448. return new Dynamic { Id = id, Type = typeof(T), Reader = ReaderDataSerializer<T>, Writer = WriterDataSerializer<T> };
  2449. }
  2450. private static Dynamic GetDynamicArray<T>(FourCC id) where T : IDataSerializable, new()
  2451. {
  2452. return new Dynamic { Id = id, Type = typeof(T[]), Reader = ReaderDataSerializerArray<T>, Writer = WriterDataSerializerArray<T> };
  2453. }
  2454. private static Dynamic GetDynamicList<T>(FourCC id) where T : IDataSerializable, new()
  2455. {
  2456. return new Dynamic { Id = id, Type = typeof(List<T>), Reader = ReaderDataSerializerList<T>, Writer = WriterDataSerializerList<T> };
  2457. }
  2458. private class Dynamic
  2459. {
  2460. public FourCC Id;
  2461. public Type Type;
  2462. public ReadRef Reader;
  2463. public WriteRef Writer;
  2464. public SerializerAction DynamicSerializer;
  2465. public object DynamicReader<T>(BinarySerializer serializer) where T : new()
  2466. {
  2467. object value = new T();
  2468. DynamicSerializer(ref value, serializer);
  2469. return value;
  2470. }
  2471. public void DynamicWriter(object value, BinarySerializer serializer)
  2472. {
  2473. DynamicSerializer(ref value, serializer);
  2474. }
  2475. }
  2476. protected override void Dispose(bool disposing)
  2477. {
  2478. }
  2479. }
  2480. }