Decompiled source of OdinSerializer v2022.11.9

BepInEx/plugins/Odin Serializer/OdinSerializer.dll

Decompiled a year ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Assemblies;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using JetBrains.Annotations;
using OdinSerializer;
using OdinSerializer.Utilities;
using OdinSerializer.Utilities.Unsafe;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RegisterFormatterLocator(typeof(ArrayFormatterLocator), -80)]
[assembly: RegisterFormatterLocator(typeof(DelegateFormatterLocator), -50)]
[assembly: RegisterFormatterLocator(typeof(GenericCollectionFormatterLocator), -100)]
[assembly: RegisterFormatterLocator(typeof(ISerializableFormatterLocator), -110)]
[assembly: RegisterFormatterLocator(typeof(SelfFormatterLocator), -60)]
[assembly: RegisterFormatterLocator(typeof(TypeFormatterLocator), -70)]
[assembly: RegisterFormatter(typeof(ArrayListFormatter), 0)]
[assembly: RegisterFormatter(typeof(DateTimeFormatter), 0)]
[assembly: RegisterFormatter(typeof(DateTimeOffsetFormatter), 0)]
[assembly: RegisterFormatter(typeof(DerivedDictionaryFormatter<, , >), typeof(WeakDictionaryFormatter), -1)]
[assembly: RegisterFormatter(typeof(DictionaryFormatter<, >), typeof(WeakDictionaryFormatter), 0)]
[assembly: RegisterFormatter(typeof(DoubleLookupDictionaryFormatter<, , >), typeof(WeakDoubleLookupDictionaryFormatter), 0)]
[assembly: RegisterFormatter(typeof(HashSetFormatter<>), typeof(WeakHashSetFormatter), 0)]
[assembly: RegisterFormatter(typeof(KeyValuePairFormatter<, >), typeof(WeakKeyValuePairFormatter), 0)]
[assembly: RegisterFormatter(typeof(ListFormatter<>), typeof(WeakListFormatter), 0)]
[assembly: RegisterFormatter(typeof(MethodInfoFormatter<>), typeof(WeakMethodInfoFormatter), 0)]
[assembly: RegisterFormatter(typeof(NullableFormatter<>), typeof(WeakNullableFormatter), 0)]
[assembly: RegisterFormatter(typeof(QueueFormatter<, >), typeof(WeakQueueFormatter), 0)]
[assembly: RegisterFormatter(typeof(StackFormatter<, >), typeof(WeakStackFormatter), 0)]
[assembly: RegisterFormatter(typeof(TimeSpanFormatter), 0)]
[assembly: RegisterFormatter(typeof(VersionFormatter), 0)]
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector2DictionaryKeyPathProvider))]
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector3DictionaryKeyPathProvider))]
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector4DictionaryKeyPathProvider))]
[assembly: RegisterFormatter(typeof(AnimationCurveFormatter), 0)]
[assembly: RegisterFormatter(typeof(BoundsFormatter), 0)]
[assembly: RegisterFormatter(typeof(Color32Formatter), 0)]
[assembly: RegisterFormatterLocator(typeof(ColorBlockFormatterLocator), 0)]
[assembly: RegisterFormatter(typeof(ColorFormatter), 0)]
[assembly: RegisterFormatter(typeof(CoroutineFormatter), 0)]
[assembly: RegisterFormatter(typeof(GradientAlphaKeyFormatter), 0)]
[assembly: RegisterFormatter(typeof(GradientColorKeyFormatter), 0)]
[assembly: RegisterFormatter(typeof(GradientFormatter), 0)]
[assembly: RegisterFormatter(typeof(KeyframeFormatter), 0)]
[assembly: RegisterFormatter(typeof(LayerMaskFormatter), 0)]
[assembly: RegisterFormatter(typeof(QuaternionFormatter), 0)]
[assembly: RegisterFormatter(typeof(RectFormatter), 0)]
[assembly: RegisterFormatter(typeof(UnityEventFormatter<>), typeof(WeakUnityEventFormatter), 0)]
[assembly: RegisterFormatter(typeof(Vector2Formatter), 0)]
[assembly: RegisterFormatter(typeof(Vector3Formatter), 0)]
[assembly: RegisterFormatter(typeof(Vector4Formatter), 0)]
[assembly: RegisterFormatter(typeof(Vector2IntFormatter), 0)]
[assembly: RegisterFormatter(typeof(Vector3IntFormatter), 0)]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]
[assembly: AssemblyCompany("Lordfirespeed")]
[assembly: AssemblyConfiguration("Release JIT")]
[assembly: AssemblyFileVersion("2022.11.9.0")]
[assembly: AssemblyInformationalVersion("2022.11.9+24cbb31292337b9d9a549738169052b81ed466fb")]
[assembly: AssemblyProduct("OdinSerializer")]
[assembly: AssemblyTitle("OdinSerializer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2022.0.0.0")]
[module: UnverifiableCode]
namespace OdinSerializer
{
	public class GlobalSerializationConfig
	{
		private static readonly GlobalSerializationConfig instance = new GlobalSerializationConfig();

		public static GlobalSerializationConfig Instance => instance;

		public ILogger Logger => DefaultLoggers.UnityLogger;

		public DataFormat EditorSerializationFormat => DataFormat.Nodes;

		public DataFormat BuildSerializationFormat => DataFormat.Binary;

		public LoggingPolicy LoggingPolicy => LoggingPolicy.LogErrors;

		public ErrorHandlingPolicy ErrorHandlingPolicy => ErrorHandlingPolicy.Resilient;

		internal static bool HasInstanceLoaded => true;

		internal static void LoadInstanceIfAssetExists()
		{
		}
	}
	public abstract class BaseDataReader : BaseDataReaderWriter, IDataReader, IDisposable
	{
		private DeserializationContext context;

		private Stream stream;

		public int CurrentNodeId => base.CurrentNode.Id;

		public int CurrentNodeDepth => base.NodeDepth;

		public string CurrentNodeName => base.CurrentNode.Name;

		public virtual Stream Stream
		{
			get
			{
				return stream;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				if (!value.CanRead)
				{
					throw new ArgumentException("Cannot read from stream");
				}
				stream = value;
			}
		}

		public DeserializationContext Context
		{
			get
			{
				if (context == null)
				{
					context = new DeserializationContext();
				}
				return context;
			}
			set
			{
				context = value;
			}
		}

		protected BaseDataReader(Stream stream, DeserializationContext context)
		{
			this.context = context;
			if (stream != null)
			{
				Stream = stream;
			}
		}

		public abstract bool EnterNode(out Type type);

		public abstract bool ExitNode();

		public abstract bool EnterArray(out long length);

		public abstract bool ExitArray();

		public abstract bool ReadPrimitiveArray<T>(out T[] array) where T : struct;

		public abstract EntryType PeekEntry(out string name);

		public abstract bool ReadInternalReference(out int id);

		public abstract bool ReadExternalReference(out int index);

		public abstract bool ReadExternalReference(out Guid guid);

		public abstract bool ReadExternalReference(out string id);

		public abstract bool ReadChar(out char value);

		public abstract bool ReadString(out string value);

		public abstract bool ReadGuid(out Guid value);

		public abstract bool ReadSByte(out sbyte value);

		public abstract bool ReadInt16(out short value);

		public abstract bool ReadInt32(out int value);

		public abstract bool ReadInt64(out long value);

		public abstract bool ReadByte(out byte value);

		public abstract bool ReadUInt16(out ushort value);

		public abstract bool ReadUInt32(out uint value);

		public abstract bool ReadUInt64(out ulong value);

		public abstract bool ReadDecimal(out decimal value);

		public abstract bool ReadSingle(out float value);

		public abstract bool ReadDouble(out double value);

		public abstract bool ReadBoolean(out bool value);

		public abstract bool ReadNull();

		public virtual void SkipEntry()
		{
			switch (PeekEntry())
			{
			case EntryType.StartOfNode:
			{
				bool flag = true;
				EnterNode(out var type);
				try
				{
					if (type != null)
					{
						if (FormatterUtilities.IsPrimitiveType(type))
						{
							Serializer serializer = Serializer.Get(type);
							object reference = serializer.ReadValueWeak(this);
							if (CurrentNodeId >= 0)
							{
								Context.RegisterInternalReference(CurrentNodeId, reference);
							}
						}
						else
						{
							IFormatter formatter = FormatterLocator.GetFormatter(type, Context.Config.SerializationPolicy);
							object reference2 = formatter.Deserialize(this);
							if (CurrentNodeId >= 0)
							{
								Context.RegisterInternalReference(CurrentNodeId, reference2);
							}
						}
						break;
					}
					while (true)
					{
						switch (PeekEntry())
						{
						case EntryType.EndOfArray:
							ReadToNextEntry();
							break;
						default:
							SkipEntry();
							break;
						case EntryType.EndOfNode:
						case EntryType.EndOfStream:
							return;
						}
					}
				}
				catch (SerializationAbortException ex)
				{
					flag = false;
					throw ex;
				}
				finally
				{
					if (flag)
					{
						ExitNode();
					}
				}
			}
			case EntryType.StartOfArray:
				ReadToNextEntry();
				while (true)
				{
					switch (PeekEntry())
					{
					case EntryType.EndOfArray:
						ReadToNextEntry();
						return;
					case EntryType.EndOfNode:
						ReadToNextEntry();
						break;
					default:
						SkipEntry();
						break;
					case EntryType.EndOfStream:
						return;
					}
				}
			default:
				ReadToNextEntry();
				break;
			case EntryType.EndOfNode:
			case EntryType.EndOfArray:
				break;
			}
		}

		public abstract void Dispose();

		public virtual void PrepareNewSerializationSession()
		{
			ClearNodes();
		}

		public abstract string GetDataDump();

		protected abstract EntryType PeekEntry();

		protected abstract EntryType ReadToNextEntry();
	}
	public abstract class BaseDataReaderWriter
	{
		private NodeInfo[] nodes = new NodeInfo[32];

		private int nodesLength;

		[Obsolete("Use the Binder member on the writer's SerializationContext/DeserializationContext instead.", false)]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public TwoWaySerializationBinder Binder
		{
			get
			{
				if (this is IDataWriter)
				{
					return (this as IDataWriter).Context.Binder;
				}
				if (this is IDataReader)
				{
					return (this as IDataReader).Context.Binder;
				}
				return TwoWaySerializationBinder.Default;
			}
			set
			{
				if (this is IDataWriter)
				{
					(this as IDataWriter).Context.Binder = value;
				}
				else if (this is IDataReader)
				{
					(this as IDataReader).Context.Binder = value;
				}
			}
		}

		public bool IsInArrayNode
		{
			get
			{
				if (nodesLength != 0)
				{
					return nodes[nodesLength - 1].IsArray;
				}
				return false;
			}
		}

		protected int NodeDepth => nodesLength;

		protected NodeInfo[] NodesArray => nodes;

		protected NodeInfo CurrentNode
		{
			get
			{
				if (nodesLength != 0)
				{
					return nodes[nodesLength - 1];
				}
				return NodeInfo.Empty;
			}
		}

		protected void PushNode(NodeInfo node)
		{
			if (nodesLength == nodes.Length)
			{
				ExpandNodes();
			}
			nodes[nodesLength] = node;
			nodesLength++;
		}

		protected void PushNode(string name, int id, Type type)
		{
			if (nodesLength == nodes.Length)
			{
				ExpandNodes();
			}
			nodes[nodesLength] = new NodeInfo(name, id, type, isArray: false);
			nodesLength++;
		}

		protected void PushArray()
		{
			if (nodesLength == nodes.Length)
			{
				ExpandNodes();
			}
			if (nodesLength == 0 || nodes[nodesLength - 1].IsArray)
			{
				nodes[nodesLength] = new NodeInfo(null, -1, null, isArray: true);
			}
			else
			{
				NodeInfo nodeInfo = nodes[nodesLength - 1];
				nodes[nodesLength] = new NodeInfo(nodeInfo.Name, nodeInfo.Id, nodeInfo.Type, isArray: true);
			}
			nodesLength++;
		}

		private void ExpandNodes()
		{
			NodeInfo[] array = new NodeInfo[nodes.Length * 2];
			NodeInfo[] array2 = nodes;
			for (int i = 0; i < array2.Length; i++)
			{
				array[i] = array2[i];
			}
			nodes = array;
		}

		protected void PopNode(string name)
		{
			if (nodesLength == 0)
			{
				throw new InvalidOperationException("There are no nodes to pop.");
			}
			nodesLength--;
		}

		protected void PopArray()
		{
			if (nodesLength == 0)
			{
				throw new InvalidOperationException("There are no nodes to pop.");
			}
			if (!nodes[nodesLength - 1].IsArray)
			{
				throw new InvalidOperationException("Was not in array when exiting array.");
			}
			nodesLength--;
		}

		protected void ClearNodes()
		{
			nodesLength = 0;
		}
	}
	public abstract class BaseDataWriter : BaseDataReaderWriter, IDataWriter, IDisposable
	{
		private SerializationContext context;

		private Stream stream;

		public virtual Stream Stream
		{
			get
			{
				return stream;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				if (!value.CanWrite)
				{
					throw new ArgumentException("Cannot write to stream");
				}
				stream = value;
			}
		}

		public SerializationContext Context
		{
			get
			{
				if (context == null)
				{
					context = new SerializationContext();
				}
				return context;
			}
			set
			{
				context = value;
			}
		}

		protected BaseDataWriter(Stream stream, SerializationContext context)
		{
			this.context = context;
			if (stream != null)
			{
				Stream = stream;
			}
		}

		public virtual void FlushToStream()
		{
			Stream.Flush();
		}

		public abstract void BeginReferenceNode(string name, Type type, int id);

		public abstract void BeginStructNode(string name, Type type);

		public abstract void EndNode(string name);

		public abstract void BeginArrayNode(long length);

		public abstract void EndArrayNode();

		public abstract void WritePrimitiveArray<T>(T[] array) where T : struct;

		public abstract void WriteNull(string name);

		public abstract void WriteInternalReference(string name, int id);

		public abstract void WriteExternalReference(string name, int index);

		public abstract void WriteExternalReference(string name, Guid guid);

		public abstract void WriteExternalReference(string name, string id);

		public abstract void WriteChar(string name, char value);

		public abstract void WriteString(string name, string value);

		public abstract void WriteGuid(string name, Guid value);

		public abstract void WriteSByte(string name, sbyte value);

		public abstract void WriteInt16(string name, short value);

		public abstract void WriteInt32(string name, int value);

		public abstract void WriteInt64(string name, long value);

		public abstract void WriteByte(string name, byte value);

		public abstract void WriteUInt16(string name, ushort value);

		public abstract void WriteUInt32(string name, uint value);

		public abstract void WriteUInt64(string name, ulong value);

		public abstract void WriteDecimal(string name, decimal value);

		public abstract void WriteSingle(string name, float value);

		public abstract void WriteDouble(string name, double value);

		public abstract void WriteBoolean(string name, bool value);

		public abstract void Dispose();

		public virtual void PrepareNewSerializationSession()
		{
			ClearNodes();
		}

		public abstract string GetDataDump();
	}
	public class BinaryDataReader : BaseDataReader
	{
		private struct Struct256Bit
		{
			public decimal d1;

			public decimal d2;
		}

		private static readonly Dictionary<Type, Delegate> PrimitiveFromByteMethods = new Dictionary<Type, Delegate>
		{
			{
				typeof(char),
				(Func<byte[], int, char>)((byte[] b, int i) => (char)ProperBitConverter.ToUInt16(b, i))
			},
			{
				typeof(byte),
				(Func<byte[], int, byte>)((byte[] b, int i) => b[i])
			},
			{
				typeof(sbyte),
				(Func<byte[], int, sbyte>)((byte[] b, int i) => (sbyte)b[i])
			},
			{
				typeof(bool),
				(Func<byte[], int, bool>)((byte[] b, int i) => b[i] != 0)
			},
			{
				typeof(short),
				new Func<byte[], int, short>(ProperBitConverter.ToInt16)
			},
			{
				typeof(int),
				new Func<byte[], int, int>(ProperBitConverter.ToInt32)
			},
			{
				typeof(long),
				new Func<byte[], int, long>(ProperBitConverter.ToInt64)
			},
			{
				typeof(ushort),
				new Func<byte[], int, ushort>(ProperBitConverter.ToUInt16)
			},
			{
				typeof(uint),
				new Func<byte[], int, uint>(ProperBitConverter.ToUInt32)
			},
			{
				typeof(ulong),
				new Func<byte[], int, ulong>(ProperBitConverter.ToUInt64)
			},
			{
				typeof(decimal),
				new Func<byte[], int, decimal>(ProperBitConverter.ToDecimal)
			},
			{
				typeof(float),
				new Func<byte[], int, float>(ProperBitConverter.ToSingle)
			},
			{
				typeof(double),
				new Func<byte[], int, double>(ProperBitConverter.ToDouble)
			},
			{
				typeof(Guid),
				new Func<byte[], int, Guid>(ProperBitConverter.ToGuid)
			}
		};

		private byte[] internalBufferBackup;

		private byte[] buffer = new byte[102400];

		private int bufferIndex;

		private int bufferEnd;

		private EntryType? peekedEntryType;

		private BinaryEntryType peekedBinaryEntryType;

		private string peekedEntryName;

		private Dictionary<int, Type> types = new Dictionary<int, Type>(16);

		public BinaryDataReader()
			: base(null, null)
		{
			internalBufferBackup = buffer;
		}

		public BinaryDataReader(Stream stream, DeserializationContext context)
			: base(stream, context)
		{
			internalBufferBackup = buffer;
		}

		public override void Dispose()
		{
		}

		public override EntryType PeekEntry(out string name)
		{
			if (peekedEntryType.HasValue)
			{
				name = peekedEntryName;
				return peekedEntryType.Value;
			}
			peekedBinaryEntryType = (BinaryEntryType)(HasBufferData(1) ? buffer[bufferIndex++] : 49);
			switch (peekedBinaryEntryType)
			{
			case BinaryEntryType.EndOfStream:
				name = null;
				peekedEntryName = null;
				peekedEntryType = EntryType.EndOfStream;
				break;
			case BinaryEntryType.NamedStartOfReferenceNode:
			case BinaryEntryType.NamedStartOfStructNode:
				name = ReadStringValue();
				peekedEntryType = EntryType.StartOfNode;
				break;
			case BinaryEntryType.UnnamedStartOfReferenceNode:
			case BinaryEntryType.UnnamedStartOfStructNode:
				name = null;
				peekedEntryType = EntryType.StartOfNode;
				break;
			case BinaryEntryType.EndOfNode:
				name = null;
				peekedEntryType = EntryType.EndOfNode;
				break;
			case BinaryEntryType.StartOfArray:
				name = null;
				peekedEntryType = EntryType.StartOfArray;
				break;
			case BinaryEntryType.EndOfArray:
				name = null;
				peekedEntryType = EntryType.EndOfArray;
				break;
			case BinaryEntryType.PrimitiveArray:
				name = null;
				peekedEntryType = EntryType.PrimitiveArray;
				break;
			case BinaryEntryType.NamedInternalReference:
				name = ReadStringValue();
				peekedEntryType = EntryType.InternalReference;
				break;
			case BinaryEntryType.UnnamedInternalReference:
				name = null;
				peekedEntryType = EntryType.InternalReference;
				break;
			case BinaryEntryType.NamedExternalReferenceByIndex:
				name = ReadStringValue();
				peekedEntryType = EntryType.ExternalReferenceByIndex;
				break;
			case BinaryEntryType.UnnamedExternalReferenceByIndex:
				name = null;
				peekedEntryType = EntryType.ExternalReferenceByIndex;
				break;
			case BinaryEntryType.NamedExternalReferenceByGuid:
				name = ReadStringValue();
				peekedEntryType = EntryType.ExternalReferenceByGuid;
				break;
			case BinaryEntryType.UnnamedExternalReferenceByGuid:
				name = null;
				peekedEntryType = EntryType.ExternalReferenceByGuid;
				break;
			case BinaryEntryType.NamedExternalReferenceByString:
				name = ReadStringValue();
				peekedEntryType = EntryType.ExternalReferenceByString;
				break;
			case BinaryEntryType.UnnamedExternalReferenceByString:
				name = null;
				peekedEntryType = EntryType.ExternalReferenceByString;
				break;
			case BinaryEntryType.NamedSByte:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedSByte:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedByte:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedByte:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedShort:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedShort:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedUShort:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedUShort:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedInt:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedInt:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedUInt:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedUInt:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedLong:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedLong:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedULong:
				name = ReadStringValue();
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.UnnamedULong:
				name = null;
				peekedEntryType = EntryType.Integer;
				break;
			case BinaryEntryType.NamedFloat:
				name = ReadStringValue();
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.UnnamedFloat:
				name = null;
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.NamedDouble:
				name = ReadStringValue();
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.UnnamedDouble:
				name = null;
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.NamedDecimal:
				name = ReadStringValue();
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.UnnamedDecimal:
				name = null;
				peekedEntryType = EntryType.FloatingPoint;
				break;
			case BinaryEntryType.NamedChar:
				name = ReadStringValue();
				peekedEntryType = EntryType.String;
				break;
			case BinaryEntryType.UnnamedChar:
				name = null;
				peekedEntryType = EntryType.String;
				break;
			case BinaryEntryType.NamedString:
				name = ReadStringValue();
				peekedEntryType = EntryType.String;
				break;
			case BinaryEntryType.UnnamedString:
				name = null;
				peekedEntryType = EntryType.String;
				break;
			case BinaryEntryType.NamedGuid:
				name = ReadStringValue();
				peekedEntryType = EntryType.Guid;
				break;
			case BinaryEntryType.UnnamedGuid:
				name = null;
				peekedEntryType = EntryType.Guid;
				break;
			case BinaryEntryType.NamedBoolean:
				name = ReadStringValue();
				peekedEntryType = EntryType.Boolean;
				break;
			case BinaryEntryType.UnnamedBoolean:
				name = null;
				peekedEntryType = EntryType.Boolean;
				break;
			case BinaryEntryType.NamedNull:
				name = ReadStringValue();
				peekedEntryType = EntryType.Null;
				break;
			case BinaryEntryType.UnnamedNull:
				name = null;
				peekedEntryType = EntryType.Null;
				break;
			case BinaryEntryType.TypeName:
			case BinaryEntryType.TypeID:
				peekedBinaryEntryType = BinaryEntryType.Invalid;
				peekedEntryType = EntryType.Invalid;
				throw new InvalidOperationException("Invalid binary data stream: BinaryEntryType.TypeName and BinaryEntryType.TypeID must never be peeked by the binary reader.");
			default:
			{
				name = null;
				peekedBinaryEntryType = BinaryEntryType.Invalid;
				peekedEntryType = EntryType.Invalid;
				byte b = (byte)peekedBinaryEntryType;
				throw new InvalidOperationException("Invalid binary data stream: could not parse peeked BinaryEntryType byte '" + b + "' into a known entry type.");
			}
			}
			peekedEntryName = name;
			return peekedEntryType.Value;
		}

		public override bool EnterArray(out long length)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedEntryType == EntryType.StartOfArray)
			{
				PushArray();
				MarkEntryContentConsumed();
				if (UNSAFE_Read_8_Int64(out length))
				{
					if (length < 0)
					{
						length = 0L;
						base.Context.Config.DebugContext.LogError("Invalid array length: " + length + ".");
						return false;
					}
					return true;
				}
				return false;
			}
			SkipEntry();
			length = 0L;
			return false;
		}

		public override bool EnterNode(out Type type)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedStartOfReferenceNode || peekedBinaryEntryType == BinaryEntryType.UnnamedStartOfReferenceNode)
			{
				MarkEntryContentConsumed();
				type = ReadTypeEntry();
				if (!UNSAFE_Read_4_Int32(out var value))
				{
					type = null;
					return false;
				}
				PushNode(peekedEntryName, value, type);
				return true;
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedStartOfStructNode || peekedBinaryEntryType == BinaryEntryType.UnnamedStartOfStructNode)
			{
				type = ReadTypeEntry();
				PushNode(peekedEntryName, -1, type);
				MarkEntryContentConsumed();
				return true;
			}
			SkipEntry();
			type = null;
			return false;
		}

		public override bool ExitArray()
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			while (peekedBinaryEntryType != BinaryEntryType.EndOfArray && peekedBinaryEntryType != BinaryEntryType.EndOfStream)
			{
				if (peekedEntryType == EntryType.EndOfNode)
				{
					base.Context.Config.DebugContext.LogError("Data layout mismatch; skipping past node boundary when exiting array.");
					MarkEntryContentConsumed();
				}
				SkipEntry();
			}
			if (peekedBinaryEntryType == BinaryEntryType.EndOfArray)
			{
				MarkEntryContentConsumed();
				PopArray();
				return true;
			}
			return false;
		}

		public override bool ExitNode()
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			while (peekedBinaryEntryType != BinaryEntryType.EndOfNode && peekedBinaryEntryType != BinaryEntryType.EndOfStream)
			{
				if (peekedEntryType == EntryType.EndOfArray)
				{
					base.Context.Config.DebugContext.LogError("Data layout mismatch; skipping past array boundary when exiting node.");
					MarkEntryContentConsumed();
				}
				SkipEntry();
			}
			if (peekedBinaryEntryType == BinaryEntryType.EndOfNode)
			{
				MarkEntryContentConsumed();
				PopNode(base.CurrentNodeName);
				return true;
			}
			return false;
		}

		public unsafe override bool ReadPrimitiveArray<T>(out T[] array)
		{
			if (!FormatterUtilities.IsPrimitiveArrayType(typeof(T)))
			{
				throw new ArgumentException("Type " + typeof(T).Name + " is not a valid primitive array type.");
			}
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedEntryType == EntryType.PrimitiveArray)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_4_Int32(out var value) || !UNSAFE_Read_4_Int32(out var value2))
				{
					array = null;
					return false;
				}
				int num = value * value2;
				if (!HasBufferData(num))
				{
					bufferIndex = bufferEnd;
					array = null;
					return false;
				}
				if (typeof(T) == typeof(byte))
				{
					byte[] array2 = new byte[num];
					Buffer.BlockCopy(buffer, bufferIndex, array2, 0, num);
					array = (T[])(object)array2;
					bufferIndex += num;
					return true;
				}
				array = new T[value];
				if (BitConverter.IsLittleEndian)
				{
					GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
					try
					{
						fixed (byte* ptr = buffer)
						{
							void* from = ptr + bufferIndex;
							void* to = gCHandle.AddrOfPinnedObject().ToPointer();
							UnsafeUtilities.MemoryCopy(from, to, num);
						}
					}
					finally
					{
						gCHandle.Free();
					}
				}
				else
				{
					Func<byte[], int, T> func = (Func<byte[], int, T>)PrimitiveFromByteMethods[typeof(T)];
					for (int i = 0; i < value; i++)
					{
						array[i] = func(buffer, bufferIndex + i * value2);
					}
				}
				bufferIndex += num;
				return true;
			}
			SkipEntry();
			array = null;
			return false;
		}

		public override bool ReadBoolean(out bool value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedEntryType == EntryType.Boolean)
			{
				MarkEntryContentConsumed();
				if (HasBufferData(1))
				{
					value = buffer[bufferIndex++] == 1;
					return true;
				}
				value = false;
				return false;
			}
			SkipEntry();
			value = false;
			return false;
		}

		public override bool ReadSByte(out sbyte value)
		{
			if (ReadInt64(out var value2))
			{
				try
				{
					value = checked((sbyte)value2);
				}
				catch (OverflowException)
				{
					value = 0;
				}
				return true;
			}
			value = 0;
			return false;
		}

		public override bool ReadByte(out byte value)
		{
			if (ReadUInt64(out var value2))
			{
				try
				{
					value = checked((byte)value2);
				}
				catch (OverflowException)
				{
					value = 0;
				}
				return true;
			}
			value = 0;
			return false;
		}

		public override bool ReadInt16(out short value)
		{
			if (ReadInt64(out var value2))
			{
				try
				{
					value = checked((short)value2);
				}
				catch (OverflowException)
				{
					value = 0;
				}
				return true;
			}
			value = 0;
			return false;
		}

		public override bool ReadUInt16(out ushort value)
		{
			if (ReadUInt64(out var value2))
			{
				try
				{
					value = checked((ushort)value2);
				}
				catch (OverflowException)
				{
					value = 0;
				}
				return true;
			}
			value = 0;
			return false;
		}

		public override bool ReadInt32(out int value)
		{
			if (ReadInt64(out var value2))
			{
				try
				{
					value = checked((int)value2);
				}
				catch (OverflowException)
				{
					value = 0;
				}
				return true;
			}
			value = 0;
			return false;
		}

		public override bool ReadUInt32(out uint value)
		{
			if (ReadUInt64(out var value2))
			{
				try
				{
					value = checked((uint)value2);
				}
				catch (OverflowException)
				{
					value = 0u;
				}
				return true;
			}
			value = 0u;
			return false;
		}

		public override bool ReadInt64(out long value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedEntryType == EntryType.Integer)
			{
				try
				{
					switch (peekedBinaryEntryType)
					{
					case BinaryEntryType.NamedSByte:
					case BinaryEntryType.UnnamedSByte:
					{
						if (!UNSAFE_Read_1_SByte(out var value5))
						{
							value = 0L;
							return false;
						}
						value = value5;
						break;
					}
					case BinaryEntryType.NamedByte:
					case BinaryEntryType.UnnamedByte:
					{
						if (!UNSAFE_Read_1_Byte(out var value6))
						{
							value = 0L;
							return false;
						}
						value = value6;
						break;
					}
					case BinaryEntryType.NamedShort:
					case BinaryEntryType.UnnamedShort:
					{
						if (!UNSAFE_Read_2_Int16(out var value7))
						{
							value = 0L;
							return false;
						}
						value = value7;
						break;
					}
					case BinaryEntryType.NamedUShort:
					case BinaryEntryType.UnnamedUShort:
					{
						if (!UNSAFE_Read_2_UInt16(out var value3))
						{
							value = 0L;
							return false;
						}
						value = value3;
						break;
					}
					case BinaryEntryType.NamedInt:
					case BinaryEntryType.UnnamedInt:
					{
						if (!UNSAFE_Read_4_Int32(out var value4))
						{
							value = 0L;
							return false;
						}
						value = value4;
						break;
					}
					case BinaryEntryType.NamedUInt:
					case BinaryEntryType.UnnamedUInt:
					{
						if (!UNSAFE_Read_4_UInt32(out var value8))
						{
							value = 0L;
							return false;
						}
						value = value8;
						break;
					}
					case BinaryEntryType.NamedLong:
					case BinaryEntryType.UnnamedLong:
						if (!UNSAFE_Read_8_Int64(out value))
						{
							return false;
						}
						break;
					case BinaryEntryType.NamedULong:
					case BinaryEntryType.UnnamedULong:
					{
						if (!UNSAFE_Read_8_UInt64(out var value2))
						{
							value = 0L;
							return false;
						}
						if (value2 > long.MaxValue)
						{
							value = 0L;
							return false;
						}
						value = (long)value2;
						break;
					}
					default:
						throw new InvalidOperationException();
					}
					return true;
				}
				finally
				{
					MarkEntryContentConsumed();
				}
			}
			SkipEntry();
			value = 0L;
			return false;
		}

		public override bool ReadUInt64(out ulong value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedEntryType == EntryType.Integer)
			{
				try
				{
					switch (peekedBinaryEntryType)
					{
					case BinaryEntryType.NamedSByte:
					case BinaryEntryType.UnnamedSByte:
					case BinaryEntryType.NamedByte:
					case BinaryEntryType.UnnamedByte:
					{
						if (!UNSAFE_Read_1_Byte(out var value7))
						{
							value = 0uL;
							return false;
						}
						value = value7;
						break;
					}
					case BinaryEntryType.NamedShort:
					case BinaryEntryType.UnnamedShort:
					{
						if (!UNSAFE_Read_2_Int16(out var value4))
						{
							value = 0uL;
							return false;
						}
						if (value4 < 0)
						{
							value = 0uL;
							return false;
						}
						value = (ulong)value4;
						break;
					}
					case BinaryEntryType.NamedUShort:
					case BinaryEntryType.UnnamedUShort:
					{
						if (!UNSAFE_Read_2_UInt16(out var value6))
						{
							value = 0uL;
							return false;
						}
						value = value6;
						break;
					}
					case BinaryEntryType.NamedInt:
					case BinaryEntryType.UnnamedInt:
					{
						if (!UNSAFE_Read_4_Int32(out var value5))
						{
							value = 0uL;
							return false;
						}
						if (value5 < 0)
						{
							value = 0uL;
							return false;
						}
						value = (ulong)value5;
						break;
					}
					case BinaryEntryType.NamedUInt:
					case BinaryEntryType.UnnamedUInt:
					{
						if (!UNSAFE_Read_4_UInt32(out var value2))
						{
							value = 0uL;
							return false;
						}
						value = value2;
						break;
					}
					case BinaryEntryType.NamedLong:
					case BinaryEntryType.UnnamedLong:
					{
						if (!UNSAFE_Read_8_Int64(out var value3))
						{
							value = 0uL;
							return false;
						}
						if (value3 < 0)
						{
							value = 0uL;
							return false;
						}
						value = (ulong)value3;
						break;
					}
					case BinaryEntryType.NamedULong:
					case BinaryEntryType.UnnamedULong:
						if (!UNSAFE_Read_8_UInt64(out value))
						{
							return false;
						}
						break;
					default:
						throw new InvalidOperationException();
					}
					return true;
				}
				finally
				{
					MarkEntryContentConsumed();
				}
			}
			SkipEntry();
			value = 0uL;
			return false;
		}

		public override bool ReadChar(out char value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedChar || peekedBinaryEntryType == BinaryEntryType.UnnamedChar)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_2_Char(out value);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedString || peekedBinaryEntryType == BinaryEntryType.UnnamedString)
			{
				MarkEntryContentConsumed();
				string text = ReadStringValue();
				if (text == null || text.Length == 0)
				{
					value = '\0';
					return false;
				}
				value = text[0];
				return true;
			}
			SkipEntry();
			value = '\0';
			return false;
		}

		public override bool ReadSingle(out float value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedFloat || peekedBinaryEntryType == BinaryEntryType.UnnamedFloat)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_4_Float32(out value);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDouble || peekedBinaryEntryType == BinaryEntryType.UnnamedDouble)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_8_Float64(out var value2))
				{
					value = 0f;
					return false;
				}
				try
				{
					value = (float)value2;
				}
				catch (OverflowException)
				{
					value = 0f;
				}
				return true;
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDecimal || peekedBinaryEntryType == BinaryEntryType.UnnamedDecimal)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_16_Decimal(out var value3))
				{
					value = 0f;
					return false;
				}
				try
				{
					value = (float)value3;
				}
				catch (OverflowException)
				{
					value = 0f;
				}
				return true;
			}
			if (peekedEntryType == EntryType.Integer)
			{
				if (!ReadInt64(out var value4))
				{
					value = 0f;
					return false;
				}
				try
				{
					value = value4;
				}
				catch (OverflowException)
				{
					value = 0f;
				}
				return true;
			}
			SkipEntry();
			value = 0f;
			return false;
		}

		public override bool ReadDouble(out double value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDouble || peekedBinaryEntryType == BinaryEntryType.UnnamedDouble)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_8_Float64(out value);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedFloat || peekedBinaryEntryType == BinaryEntryType.UnnamedFloat)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_4_Float32(out var value2))
				{
					value = 0.0;
					return false;
				}
				value = value2;
				return true;
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDecimal || peekedBinaryEntryType == BinaryEntryType.UnnamedDecimal)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_16_Decimal(out var value3))
				{
					value = 0.0;
					return false;
				}
				try
				{
					value = (double)value3;
				}
				catch (OverflowException)
				{
					value = 0.0;
				}
				return true;
			}
			if (peekedEntryType == EntryType.Integer)
			{
				if (!ReadInt64(out var value4))
				{
					value = 0.0;
					return false;
				}
				try
				{
					value = value4;
				}
				catch (OverflowException)
				{
					value = 0.0;
				}
				return true;
			}
			SkipEntry();
			value = 0.0;
			return false;
		}

		public override bool ReadDecimal(out decimal value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDecimal || peekedBinaryEntryType == BinaryEntryType.UnnamedDecimal)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_16_Decimal(out value);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedDouble || peekedBinaryEntryType == BinaryEntryType.UnnamedDouble)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_8_Float64(out var value2))
				{
					value = default(decimal);
					return false;
				}
				try
				{
					value = (decimal)value2;
				}
				catch (OverflowException)
				{
					value = default(decimal);
				}
				return true;
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedFloat || peekedBinaryEntryType == BinaryEntryType.UnnamedFloat)
			{
				MarkEntryContentConsumed();
				if (!UNSAFE_Read_4_Float32(out var value3))
				{
					value = default(decimal);
					return false;
				}
				try
				{
					value = (decimal)value3;
				}
				catch (OverflowException)
				{
					value = default(decimal);
				}
				return true;
			}
			if (peekedEntryType == EntryType.Integer)
			{
				if (!ReadInt64(out var value4))
				{
					value = default(decimal);
					return false;
				}
				try
				{
					value = value4;
				}
				catch (OverflowException)
				{
					value = default(decimal);
				}
				return true;
			}
			SkipEntry();
			value = default(decimal);
			return false;
		}

		public override bool ReadExternalReference(out Guid guid)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedExternalReferenceByGuid || peekedBinaryEntryType == BinaryEntryType.UnnamedExternalReferenceByGuid)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_16_Guid(out guid);
			}
			SkipEntry();
			guid = default(Guid);
			return false;
		}

		public override bool ReadGuid(out Guid value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedGuid || peekedBinaryEntryType == BinaryEntryType.UnnamedGuid)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_16_Guid(out value);
			}
			SkipEntry();
			value = default(Guid);
			return false;
		}

		public override bool ReadExternalReference(out int index)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedExternalReferenceByIndex || peekedBinaryEntryType == BinaryEntryType.UnnamedExternalReferenceByIndex)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_4_Int32(out index);
			}
			SkipEntry();
			index = -1;
			return false;
		}

		public override bool ReadExternalReference(out string id)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedExternalReferenceByString || peekedBinaryEntryType == BinaryEntryType.UnnamedExternalReferenceByString)
			{
				id = ReadStringValue();
				MarkEntryContentConsumed();
				return id != null;
			}
			SkipEntry();
			id = null;
			return false;
		}

		public override bool ReadNull()
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedNull || peekedBinaryEntryType == BinaryEntryType.UnnamedNull)
			{
				MarkEntryContentConsumed();
				return true;
			}
			SkipEntry();
			return false;
		}

		public override bool ReadInternalReference(out int id)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedInternalReference || peekedBinaryEntryType == BinaryEntryType.UnnamedInternalReference)
			{
				MarkEntryContentConsumed();
				return UNSAFE_Read_4_Int32(out id);
			}
			SkipEntry();
			id = -1;
			return false;
		}

		public override bool ReadString(out string value)
		{
			if (!peekedEntryType.HasValue)
			{
				PeekEntry(out var _);
			}
			if (peekedBinaryEntryType == BinaryEntryType.NamedString || peekedBinaryEntryType == BinaryEntryType.UnnamedString)
			{
				value = ReadStringValue();
				MarkEntryContentConsumed();
				return value != null;
			}
			SkipEntry();
			value = null;
			return false;
		}

		public override void PrepareNewSerializationSession()
		{
			base.PrepareNewSerializationSession();
			peekedEntryType = null;
			peekedEntryName = null;
			peekedBinaryEntryType = BinaryEntryType.Invalid;
			types.Clear();
			bufferIndex = 0;
			bufferEnd = 0;
			buffer = internalBufferBackup;
		}

		public unsafe override string GetDataDump()
		{
			byte[] array;
			if (bufferEnd == buffer.Length)
			{
				array = buffer;
			}
			else
			{
				array = new byte[bufferEnd];
				fixed (byte* ptr = buffer)
				{
					void* from = ptr;
					fixed (byte* ptr2 = array)
					{
						void* to = ptr2;
						UnsafeUtilities.MemoryCopy(from, to, array.Length);
					}
				}
			}
			return "Binary hex dump: " + ProperBitConverter.BytesToHexString(array);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe string ReadStringValue()
		{
			if (!UNSAFE_Read_1_Byte(out var value))
			{
				return null;
			}
			if (!UNSAFE_Read_4_Int32(out var value2))
			{
				return null;
			}
			string text = new string(' ', value2);
			if (value == 0)
			{
				fixed (byte* ptr = buffer)
				{
					fixed (char* ptr3 = text)
					{
						byte* ptr2 = ptr + bufferIndex;
						byte* ptr4 = (byte*)ptr3;
						if (BitConverter.IsLittleEndian)
						{
							for (int i = 0; i < value2; i++)
							{
								*(ptr4++) = *(ptr2++);
								ptr4++;
							}
						}
						else
						{
							for (int j = 0; j < value2; j++)
							{
								ptr4++;
								*(ptr4++) = *(ptr2++);
							}
						}
					}
				}
				bufferIndex += value2;
				return text;
			}
			int num = value2 * 2;
			fixed (byte* ptr5 = buffer)
			{
				fixed (char* ptr7 = text)
				{
					if (BitConverter.IsLittleEndian)
					{
						Struct256Bit* ptr6 = (Struct256Bit*)(ptr5 + bufferIndex);
						Struct256Bit* ptr8 = (Struct256Bit*)ptr7;
						byte* ptr9 = (byte*)ptr7 + num;
						while (ptr8 + 1 < ptr9)
						{
							*(ptr8++) = *(ptr6++);
						}
						byte* ptr10 = (byte*)ptr6;
						byte* ptr11 = (byte*)ptr8;
						while (ptr11 < ptr9)
						{
							*(ptr11++) = *(ptr10++);
						}
					}
					else
					{
						byte* ptr12 = ptr5 + bufferIndex;
						byte* ptr13 = (byte*)ptr7;
						for (int k = 0; k < value2; k++)
						{
							*ptr13 = ptr12[1];
							ptr13[1] = *ptr12;
							ptr12 += 2;
							ptr13 += 2;
						}
					}
				}
			}
			bufferIndex += num;
			return text;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SkipStringValue()
		{
			if (UNSAFE_Read_1_Byte(out var value) && UNSAFE_Read_4_Int32(out var value2))
			{
				if (value != 0)
				{
					value2 *= 2;
				}
				if (HasBufferData(value2))
				{
					bufferIndex += value2;
				}
				else
				{
					bufferIndex = bufferEnd;
				}
			}
		}

		private void SkipPeekedEntryContent()
		{
			if (!peekedEntryType.HasValue)
			{
				return;
			}
			try
			{
				switch (peekedBinaryEntryType)
				{
				case BinaryEntryType.NamedStartOfReferenceNode:
				case BinaryEntryType.UnnamedStartOfReferenceNode:
					ReadTypeEntry();
					if (SkipBuffer(4))
					{
					}
					break;
				case BinaryEntryType.NamedStartOfStructNode:
				case BinaryEntryType.UnnamedStartOfStructNode:
					ReadTypeEntry();
					break;
				case BinaryEntryType.StartOfArray:
					SkipBuffer(8);
					break;
				case BinaryEntryType.PrimitiveArray:
				{
					if (UNSAFE_Read_4_Int32(out var value) && UNSAFE_Read_4_Int32(out var value2))
					{
						SkipBuffer(value * value2);
					}
					break;
				}
				case BinaryEntryType.NamedSByte:
				case BinaryEntryType.UnnamedSByte:
				case BinaryEntryType.NamedByte:
				case BinaryEntryType.UnnamedByte:
				case BinaryEntryType.NamedBoolean:
				case BinaryEntryType.UnnamedBoolean:
					SkipBuffer(1);
					break;
				case BinaryEntryType.NamedShort:
				case BinaryEntryType.UnnamedShort:
				case BinaryEntryType.NamedUShort:
				case BinaryEntryType.UnnamedUShort:
				case BinaryEntryType.NamedChar:
				case BinaryEntryType.UnnamedChar:
					SkipBuffer(2);
					break;
				case BinaryEntryType.NamedInternalReference:
				case BinaryEntryType.UnnamedInternalReference:
				case BinaryEntryType.NamedExternalReferenceByIndex:
				case BinaryEntryType.UnnamedExternalReferenceByIndex:
				case BinaryEntryType.NamedInt:
				case BinaryEntryType.UnnamedInt:
				case BinaryEntryType.NamedUInt:
				case BinaryEntryType.UnnamedUInt:
				case BinaryEntryType.NamedFloat:
				case BinaryEntryType.UnnamedFloat:
					SkipBuffer(4);
					break;
				case BinaryEntryType.NamedLong:
				case BinaryEntryType.UnnamedLong:
				case BinaryEntryType.NamedULong:
				case BinaryEntryType.UnnamedULong:
				case BinaryEntryType.NamedDouble:
				case BinaryEntryType.UnnamedDouble:
					SkipBuffer(8);
					break;
				case BinaryEntryType.NamedExternalReferenceByGuid:
				case BinaryEntryType.UnnamedExternalReferenceByGuid:
				case BinaryEntryType.NamedDecimal:
				case BinaryEntryType.UnnamedDecimal:
				case BinaryEntryType.NamedGuid:
				case BinaryEntryType.UnnamedGuid:
					SkipBuffer(8);
					break;
				case BinaryEntryType.NamedString:
				case BinaryEntryType.UnnamedString:
				case BinaryEntryType.NamedExternalReferenceByString:
				case BinaryEntryType.UnnamedExternalReferenceByString:
					SkipStringValue();
					break;
				case BinaryEntryType.TypeName:
					base.Context.Config.DebugContext.LogError("Parsing error in binary data reader: should not be able to peek a TypeName entry.");
					SkipBuffer(4);
					ReadStringValue();
					break;
				case BinaryEntryType.TypeID:
					base.Context.Config.DebugContext.LogError("Parsing error in binary data reader: should not be able to peek a TypeID entry.");
					SkipBuffer(4);
					break;
				case BinaryEntryType.Invalid:
				case BinaryEntryType.EndOfNode:
				case BinaryEntryType.EndOfArray:
				case BinaryEntryType.NamedNull:
				case BinaryEntryType.UnnamedNull:
				case BinaryEntryType.EndOfStream:
					break;
				}
			}
			finally
			{
				MarkEntryContentConsumed();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private bool SkipBuffer(int amount)
		{
			int num = bufferIndex + amount;
			if (num > bufferEnd)
			{
				bufferIndex = bufferEnd;
				return false;
			}
			bufferIndex = num;
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private Type ReadTypeEntry()
		{
			if (!HasBufferData(1))
			{
				return null;
			}
			BinaryEntryType binaryEntryType = (BinaryEntryType)buffer[bufferIndex++];
			int value2;
			Type value;
			switch (binaryEntryType)
			{
			case BinaryEntryType.TypeID:
				if (!UNSAFE_Read_4_Int32(out value2))
				{
					return null;
				}
				if (!types.TryGetValue(value2, out value))
				{
					base.Context.Config.DebugContext.LogError("Missing type ID during deserialization: " + value2 + " at node " + base.CurrentNodeName + " and depth " + base.CurrentNodeDepth + " and id " + base.CurrentNodeId);
				}
				break;
			case BinaryEntryType.TypeName:
			{
				if (!UNSAFE_Read_4_Int32(out value2))
				{
					return null;
				}
				string text = ReadStringValue();
				value = ((text == null) ? null : base.Context.Binder.BindToType(text, base.Context.Config.DebugContext));
				types.Add(value2, value);
				break;
			}
			case BinaryEntryType.UnnamedNull:
				value = null;
				break;
			default:
				value = null;
				base.Context.Config.DebugContext.LogError("Expected TypeName, TypeID or UnnamedNull entry flag for reading type data, but instead got the entry flag: " + binaryEntryType.ToString() + ".");
				break;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void MarkEntryContentConsumed()
		{
			peekedEntryType = null;
			peekedEntryName = null;
			peekedBinaryEntryType = BinaryEntryType.Invalid;
		}

		protected override EntryType PeekEntry()
		{
			string name;
			return PeekEntry(out name);
		}

		protected override EntryType ReadToNextEntry()
		{
			SkipPeekedEntryContent();
			string name;
			return PeekEntry(out name);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private bool UNSAFE_Read_1_Byte(out byte value)
		{
			if (HasBufferData(1))
			{
				value = buffer[bufferIndex++];
				return true;
			}
			value = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private bool UNSAFE_Read_1_SByte(out sbyte value)
		{
			if (HasBufferData(1))
			{
				value = (sbyte)buffer[bufferIndex++];
				return true;
			}
			value = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_2_Int16(out short value)
		{
			if (HasBufferData(2))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						value = *(short*)(ptr + bufferIndex);
					}
					else
					{
						short num = 0;
						byte* ptr2 = (byte*)(&num) + 1;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = num;
					}
				}
				bufferIndex += 2;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_2_UInt16(out ushort value)
		{
			if (HasBufferData(2))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						value = *(ushort*)(ptr + bufferIndex);
					}
					else
					{
						ushort num = 0;
						byte* ptr2 = (byte*)(&num) + 1;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = num;
					}
				}
				bufferIndex += 2;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_2_Char(out char value)
		{
			if (HasBufferData(2))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						value = *(char*)(ptr + bufferIndex);
					}
					else
					{
						char c = '\0';
						byte* ptr2 = (byte*)(&c) + 1;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = c;
					}
				}
				bufferIndex += 2;
				return true;
			}
			bufferIndex = bufferEnd;
			value = '\0';
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_4_Int32(out int value)
		{
			if (HasBufferData(4))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						value = *(int*)(ptr + bufferIndex);
					}
					else
					{
						int num = 0;
						byte* ptr2 = (byte*)(&num) + 3;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = num;
					}
				}
				bufferIndex += 4;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_4_UInt32(out uint value)
		{
			if (HasBufferData(4))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						value = *(uint*)(ptr + bufferIndex);
					}
					else
					{
						uint num = 0u;
						byte* ptr2 = (byte*)(&num) + 3;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = num;
					}
				}
				bufferIndex += 4;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0u;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_4_Float32(out float value)
		{
			if (HasBufferData(4))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_Unaligned_Float32_Reads)
						{
							value = *(float*)(ptr + bufferIndex);
						}
						else
						{
							float num = 0f;
							*(int*)(&num) = *(int*)(ptr + bufferIndex);
							value = num;
						}
					}
					else
					{
						float num2 = 0f;
						byte* ptr2 = (byte*)(&num2) + 3;
						byte* ptr3 = ptr + bufferIndex;
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*(ptr2--) = *(ptr3++);
						*ptr2 = *ptr3;
						value = num2;
					}
				}
				bufferIndex += 4;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0f;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_8_Int64(out long value)
		{
			if (HasBufferData(8))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
						{
							value = *(long*)(ptr + bufferIndex);
						}
						else
						{
							long num = 0L;
							int* ptr2 = (int*)(&num);
							int* ptr3 = (int*)(ptr + bufferIndex);
							*(ptr2++) = *(ptr3++);
							*ptr2 = *ptr3;
							value = num;
						}
					}
					else
					{
						long num2 = 0L;
						byte* ptr4 = (byte*)(&num2) + 7;
						byte* ptr5 = ptr + bufferIndex;
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*ptr4 = *ptr5;
						value = num2;
					}
				}
				bufferIndex += 8;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0L;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_8_UInt64(out ulong value)
		{
			if (HasBufferData(8))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
						{
							value = *(ulong*)(ptr + bufferIndex);
						}
						else
						{
							ulong num = 0uL;
							int* ptr2 = (int*)(&num);
							int* ptr3 = (int*)(ptr + bufferIndex);
							*(ptr2++) = *(ptr3++);
							*ptr2 = *ptr3;
							value = num;
						}
					}
					else
					{
						ulong num2 = 0uL;
						byte* ptr4 = (byte*)(&num2) + 7;
						byte* ptr5 = ptr + bufferIndex;
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*ptr4 = *ptr5;
						value = num2;
					}
				}
				bufferIndex += 8;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0uL;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_8_Float64(out double value)
		{
			if (HasBufferData(8))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
						{
							value = *(double*)(ptr + bufferIndex);
						}
						else
						{
							double num = 0.0;
							int* ptr2 = (int*)(&num);
							int* ptr3 = (int*)(ptr + bufferIndex);
							*(ptr2++) = *(ptr3++);
							*ptr2 = *ptr3;
							value = num;
						}
					}
					else
					{
						double num2 = 0.0;
						byte* ptr4 = (byte*)(&num2) + 7;
						byte* ptr5 = ptr + bufferIndex;
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*ptr4 = *ptr5;
						value = num2;
					}
				}
				bufferIndex += 8;
				return true;
			}
			bufferIndex = bufferEnd;
			value = 0.0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_16_Decimal(out decimal value)
		{
			if (HasBufferData(16))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
						{
							value = *(decimal*)(ptr + bufferIndex);
						}
						else
						{
							decimal num = default(decimal);
							int* ptr2 = (int*)(&num);
							int* ptr3 = (int*)(ptr + bufferIndex);
							*(ptr2++) = *(ptr3++);
							*(ptr2++) = *(ptr3++);
							*(ptr2++) = *(ptr3++);
							*ptr2 = *ptr3;
							value = num;
						}
					}
					else
					{
						decimal num2 = default(decimal);
						byte* ptr4 = (byte*)(&num2) + 15;
						byte* ptr5 = ptr + bufferIndex;
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*ptr4 = *ptr5;
						value = num2;
					}
				}
				bufferIndex += 16;
				return true;
			}
			bufferIndex = bufferEnd;
			value = default(decimal);
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe bool UNSAFE_Read_16_Guid(out Guid value)
		{
			if (HasBufferData(16))
			{
				fixed (byte* ptr = buffer)
				{
					if (BitConverter.IsLittleEndian)
					{
						if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
						{
							value = *(Guid*)(ptr + bufferIndex);
						}
						else
						{
							Guid guid = default(Guid);
							int* ptr2 = (int*)(&guid);
							int* ptr3 = (int*)(ptr + bufferIndex);
							*(ptr2++) = *(ptr3++);
							*(ptr2++) = *(ptr3++);
							*(ptr2++) = *(ptr3++);
							*ptr2 = *ptr3;
							value = guid;
						}
					}
					else
					{
						Guid guid2 = default(Guid);
						byte* ptr4 = (byte*)(&guid2);
						byte* ptr5 = ptr + bufferIndex;
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*(ptr4++) = *(ptr5++);
						*ptr4 = *(ptr5++);
						ptr4 += 6;
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*(ptr4--) = *(ptr5++);
						*ptr4 = *ptr5;
						value = guid2;
					}
				}
				bufferIndex += 16;
				return true;
			}
			bufferIndex = bufferEnd;
			value = default(Guid);
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private bool HasBufferData(int amount)
		{
			if (bufferEnd == 0)
			{
				ReadEntireStreamToBuffer();
			}
			return bufferIndex + amount <= bufferEnd;
		}

		private void ReadEntireStreamToBuffer()
		{
			bufferIndex = 0;
			if (Stream is MemoryStream)
			{
				try
				{
					buffer = (Stream as MemoryStream).GetBuffer();
					bufferEnd = (int)Stream.Length;
					bufferIndex = (int)Stream.Position;
					return;
				}
				catch (UnauthorizedAccessException)
				{
				}
			}
			buffer = internalBufferBackup;
			int num = (int)(Stream.Length - Stream.Position);
			if (buffer.Length >= num)
			{
				Stream.Read(buffer, 0, num);
			}
			else
			{
				buffer = new byte[num];
				Stream.Read(buffer, 0, num);
				if (num <= 10485760)
				{
					internalBufferBackup = buffer;
				}
			}
			bufferIndex = 0;
			bufferEnd = num;
		}
	}
	public class BinaryDataWriter : BaseDataWriter
	{
		private struct Struct256Bit
		{
			public decimal d1;

			public decimal d2;
		}

		private static readonly Dictionary<Type, Delegate> PrimitiveGetBytesMethods = new Dictionary<Type, Delegate>(FastTypeComparer.Instance)
		{
			{
				typeof(char),
				(Action<byte[], int, char>)delegate(byte[] b, int i, char v)
				{
					ProperBitConverter.GetBytes(b, i, v);
				}
			},
			{
				typeof(byte),
				(Action<byte[], int, byte>)delegate(byte[] b, int i, byte v)
				{
					b[i] = v;
				}
			},
			{
				typeof(sbyte),
				(Action<byte[], int, sbyte>)delegate(byte[] b, int i, sbyte v)
				{
					b[i] = (byte)v;
				}
			},
			{
				typeof(bool),
				(Action<byte[], int, bool>)delegate(byte[] b, int i, bool v)
				{
					b[i] = (v ? ((byte)1) : ((byte)0));
				}
			},
			{
				typeof(short),
				new Action<byte[], int, short>(ProperBitConverter.GetBytes)
			},
			{
				typeof(int),
				new Action<byte[], int, int>(ProperBitConverter.GetBytes)
			},
			{
				typeof(long),
				new Action<byte[], int, long>(ProperBitConverter.GetBytes)
			},
			{
				typeof(ushort),
				new Action<byte[], int, ushort>(ProperBitConverter.GetBytes)
			},
			{
				typeof(uint),
				new Action<byte[], int, uint>(ProperBitConverter.GetBytes)
			},
			{
				typeof(ulong),
				new Action<byte[], int, ulong>(ProperBitConverter.GetBytes)
			},
			{
				typeof(decimal),
				new Action<byte[], int, decimal>(ProperBitConverter.GetBytes)
			},
			{
				typeof(float),
				new Action<byte[], int, float>(ProperBitConverter.GetBytes)
			},
			{
				typeof(double),
				new Action<byte[], int, double>(ProperBitConverter.GetBytes)
			},
			{
				typeof(Guid),
				new Action<byte[], int, Guid>(ProperBitConverter.GetBytes)
			}
		};

		private static readonly Dictionary<Type, int> PrimitiveSizes = new Dictionary<Type, int>(FastTypeComparer.Instance)
		{
			{
				typeof(char),
				2
			},
			{
				typeof(byte),
				1
			},
			{
				typeof(sbyte),
				1
			},
			{
				typeof(bool),
				1
			},
			{
				typeof(short),
				2
			},
			{
				typeof(int),
				4
			},
			{
				typeof(long),
				8
			},
			{
				typeof(ushort),
				2
			},
			{
				typeof(uint),
				4
			},
			{
				typeof(ulong),
				8
			},
			{
				typeof(decimal),
				16
			},
			{
				typeof(float),
				4
			},
			{
				typeof(double),
				8
			},
			{
				typeof(Guid),
				16
			}
		};

		private readonly byte[] small_buffer = new byte[16];

		private readonly byte[] buffer = new byte[102400];

		private int bufferIndex;

		private readonly Dictionary<Type, int> types = new Dictionary<Type, int>(16, FastTypeComparer.Instance);

		public bool CompressStringsTo8BitWhenPossible;

		private static readonly Dictionary<Type, Action<BinaryDataWriter, object>> PrimitiveArrayWriters = new Dictionary<Type, Action<BinaryDataWriter, object>>(FastTypeComparer.Instance)
		{
			{
				typeof(char),
				WritePrimitiveArray_char
			},
			{
				typeof(sbyte),
				WritePrimitiveArray_sbyte
			},
			{
				typeof(short),
				WritePrimitiveArray_short
			},
			{
				typeof(int),
				WritePrimitiveArray_int
			},
			{
				typeof(long),
				WritePrimitiveArray_long
			},
			{
				typeof(byte),
				WritePrimitiveArray_byte
			},
			{
				typeof(ushort),
				WritePrimitiveArray_ushort
			},
			{
				typeof(uint),
				WritePrimitiveArray_uint
			},
			{
				typeof(ulong),
				WritePrimitiveArray_ulong
			},
			{
				typeof(decimal),
				WritePrimitiveArray_decimal
			},
			{
				typeof(bool),
				WritePrimitiveArray_bool
			},
			{
				typeof(float),
				WritePrimitiveArray_float
			},
			{
				typeof(double),
				WritePrimitiveArray_double
			},
			{
				typeof(Guid),
				WritePrimitiveArray_Guid
			}
		};

		public BinaryDataWriter()
			: base(null, null)
		{
		}

		public BinaryDataWriter(Stream stream, SerializationContext context)
			: base(stream, context)
		{
		}

		public override void BeginArrayNode(long length)
		{
			EnsureBufferSpace(9);
			buffer[bufferIndex++] = 6;
			UNSAFE_WriteToBuffer_8_Int64(length);
			PushArray();
		}

		public override void BeginReferenceNode(string name, Type type, int id)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 1;
				WriteStringFast(name);
			}
			else
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 2;
			}
			WriteType(type);
			EnsureBufferSpace(4);
			UNSAFE_WriteToBuffer_4_Int32(id);
			PushNode(name, id, type);
		}

		public override void BeginStructNode(string name, Type type)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 3;
				WriteStringFast(name);
			}
			else
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 4;
			}
			WriteType(type);
			PushNode(name, -1, type);
		}

		public override void Dispose()
		{
			FlushToStream();
		}

		public override void EndArrayNode()
		{
			PopArray();
			EnsureBufferSpace(1);
			buffer[bufferIndex++] = 7;
		}

		public override void EndNode(string name)
		{
			PopNode(name);
			EnsureBufferSpace(1);
			buffer[bufferIndex++] = 5;
		}

		private static void WritePrimitiveArray_byte(BinaryDataWriter writer, object o)
		{
			byte[] array = o as byte[];
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(1);
			writer.FlushToStream();
			writer.Stream.Write(array, 0, array.Length);
		}

		private unsafe static void WritePrimitiveArray_sbyte(BinaryDataWriter writer, object o)
		{
			sbyte[] array = o as sbyte[];
			int num = 1;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				fixed (byte* ptr2 = writer.buffer)
				{
					fixed (sbyte* ptr = array)
					{
						void* from = ptr;
						void* to = ptr2 + writer.bufferIndex;
						UnsafeUtilities.MemoryCopy(from, to, num2);
					}
				}
				writer.bufferIndex += num2;
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_bool(BinaryDataWriter writer, object o)
		{
			bool[] array = o as bool[];
			int num = 1;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				fixed (byte* ptr2 = writer.buffer)
				{
					fixed (bool* ptr = array)
					{
						void* from = ptr;
						void* to = ptr2 + writer.bufferIndex;
						UnsafeUtilities.MemoryCopy(from, to, num2);
					}
				}
				writer.bufferIndex += num2;
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_char(BinaryDataWriter writer, object o)
		{
			char[] array = o as char[];
			int num = 2;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (char* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_2_Char(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_short(BinaryDataWriter writer, object o)
		{
			short[] array = o as short[];
			int num = 2;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (short* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_2_Int16(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_int(BinaryDataWriter writer, object o)
		{
			int[] array = o as int[];
			int num = 4;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (int* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_4_Int32(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_long(BinaryDataWriter writer, object o)
		{
			long[] array = o as long[];
			int num = 8;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (long* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_8_Int64(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_ushort(BinaryDataWriter writer, object o)
		{
			ushort[] array = o as ushort[];
			int num = 2;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (ushort* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_2_UInt16(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_uint(BinaryDataWriter writer, object o)
		{
			uint[] array = o as uint[];
			int num = 4;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (uint* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_4_UInt32(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_ulong(BinaryDataWriter writer, object o)
		{
			ulong[] array = o as ulong[];
			int num = 8;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (ulong* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_8_UInt64(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_decimal(BinaryDataWriter writer, object o)
		{
			decimal[] array = o as decimal[];
			int num = 16;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (decimal* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_16_Decimal(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_float(BinaryDataWriter writer, object o)
		{
			float[] array = o as float[];
			int num = 4;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (float* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_4_Float32(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_double(BinaryDataWriter writer, object o)
		{
			double[] array = o as double[];
			int num = 8;
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (double* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_8_Float64(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		private unsafe static void WritePrimitiveArray_Guid(BinaryDataWriter writer, object o)
		{
			Guid[] array = o as Guid[];
			int num = sizeof(Guid);
			int num2 = array.Length * num;
			writer.EnsureBufferSpace(9);
			writer.buffer[writer.bufferIndex++] = 8;
			writer.UNSAFE_WriteToBuffer_4_Int32(array.Length);
			writer.UNSAFE_WriteToBuffer_4_Int32(num);
			if (writer.TryEnsureBufferSpace(num2))
			{
				if (BitConverter.IsLittleEndian)
				{
					fixed (byte* ptr2 = writer.buffer)
					{
						fixed (Guid* ptr = array)
						{
							void* from = ptr;
							void* to = ptr2 + writer.bufferIndex;
							UnsafeUtilities.MemoryCopy(from, to, num2);
						}
					}
					writer.bufferIndex += num2;
				}
				else
				{
					for (int i = 0; i < array.Length; i++)
					{
						writer.UNSAFE_WriteToBuffer_16_Guid(array[i]);
					}
				}
				return;
			}
			writer.FlushToStream();
			using Buffer<byte> buffer = Buffer<byte>.Claim(num2);
			if (BitConverter.IsLittleEndian)
			{
				UnsafeUtilities.MemoryCopy(array, buffer.Array, num2, 0, 0);
			}
			else
			{
				byte[] array2 = buffer.Array;
				for (int j = 0; j < array.Length; j++)
				{
					ProperBitConverter.GetBytes(array2, j * num, array[j]);
				}
			}
			writer.Stream.Write(buffer.Array, 0, num2);
		}

		public override void WritePrimitiveArray<T>(T[] array)
		{
			if (!PrimitiveArrayWriters.TryGetValue(typeof(T), out var value))
			{
				throw new ArgumentException("Type " + typeof(T).Name + " is not a valid primitive array type.");
			}
			value(this, array);
		}

		public override void WriteBoolean(string name, bool value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 43;
				WriteStringFast(name);
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = (value ? ((byte)1) : ((byte)0));
			}
			else
			{
				EnsureBufferSpace(2);
				buffer[bufferIndex++] = 44;
				buffer[bufferIndex++] = (value ? ((byte)1) : ((byte)0));
			}
		}

		public override void WriteByte(string name, byte value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 17;
				WriteStringFast(name);
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = value;
			}
			else
			{
				EnsureBufferSpace(2);
				buffer[bufferIndex++] = 18;
				buffer[bufferIndex++] = value;
			}
		}

		public override void WriteChar(string name, char value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 37;
				WriteStringFast(name);
				EnsureBufferSpace(2);
				UNSAFE_WriteToBuffer_2_Char(value);
			}
			else
			{
				EnsureBufferSpace(3);
				buffer[bufferIndex++] = 38;
				UNSAFE_WriteToBuffer_2_Char(value);
			}
		}

		public override void WriteDecimal(string name, decimal value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 35;
				WriteStringFast(name);
				EnsureBufferSpace(16);
				UNSAFE_WriteToBuffer_16_Decimal(value);
			}
			else
			{
				EnsureBufferSpace(17);
				buffer[bufferIndex++] = 36;
				UNSAFE_WriteToBuffer_16_Decimal(value);
			}
		}

		public override void WriteDouble(string name, double value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 33;
				WriteStringFast(name);
				EnsureBufferSpace(8);
				UNSAFE_WriteToBuffer_8_Float64(value);
			}
			else
			{
				EnsureBufferSpace(9);
				buffer[bufferIndex++] = 34;
				UNSAFE_WriteToBuffer_8_Float64(value);
			}
		}

		public override void WriteGuid(string name, Guid value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 41;
				WriteStringFast(name);
				EnsureBufferSpace(16);
				UNSAFE_WriteToBuffer_16_Guid(value);
			}
			else
			{
				EnsureBufferSpace(17);
				buffer[bufferIndex++] = 42;
				UNSAFE_WriteToBuffer_16_Guid(value);
			}
		}

		public override void WriteExternalReference(string name, Guid guid)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 13;
				WriteStringFast(name);
				EnsureBufferSpace(16);
				UNSAFE_WriteToBuffer_16_Guid(guid);
			}
			else
			{
				EnsureBufferSpace(17);
				buffer[bufferIndex++] = 14;
				UNSAFE_WriteToBuffer_16_Guid(guid);
			}
		}

		public override void WriteExternalReference(string name, int index)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 11;
				WriteStringFast(name);
				EnsureBufferSpace(4);
				UNSAFE_WriteToBuffer_4_Int32(index);
			}
			else
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 12;
				UNSAFE_WriteToBuffer_4_Int32(index);
			}
		}

		public override void WriteExternalReference(string name, string id)
		{
			if (id == null)
			{
				throw new ArgumentNullException("id");
			}
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 50;
				WriteStringFast(name);
			}
			else
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 51;
			}
			WriteStringFast(id);
		}

		public override void WriteInt32(string name, int value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 23;
				WriteStringFast(name);
				EnsureBufferSpace(4);
				UNSAFE_WriteToBuffer_4_Int32(value);
			}
			else
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 24;
				UNSAFE_WriteToBuffer_4_Int32(value);
			}
		}

		public override void WriteInt64(string name, long value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 27;
				WriteStringFast(name);
				EnsureBufferSpace(8);
				UNSAFE_WriteToBuffer_8_Int64(value);
			}
			else
			{
				EnsureBufferSpace(9);
				buffer[bufferIndex++] = 28;
				UNSAFE_WriteToBuffer_8_Int64(value);
			}
		}

		public override void WriteNull(string name)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 45;
				WriteStringFast(name);
			}
			else
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 46;
			}
		}

		public override void WriteInternalReference(string name, int id)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 9;
				WriteStringFast(name);
				EnsureBufferSpace(4);
				UNSAFE_WriteToBuffer_4_Int32(id);
			}
			else
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 10;
				UNSAFE_WriteToBuffer_4_Int32(id);
			}
		}

		public override void WriteSByte(string name, sbyte value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 15;
				WriteStringFast(name);
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = (byte)value;
			}
			else
			{
				EnsureBufferSpace(2);
				buffer[bufferIndex++] = 16;
				buffer[bufferIndex++] = (byte)value;
			}
		}

		public override void WriteInt16(string name, short value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 19;
				WriteStringFast(name);
				EnsureBufferSpace(2);
				UNSAFE_WriteToBuffer_2_Int16(value);
			}
			else
			{
				EnsureBufferSpace(3);
				buffer[bufferIndex++] = 20;
				UNSAFE_WriteToBuffer_2_Int16(value);
			}
		}

		public override void WriteSingle(string name, float value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 31;
				WriteStringFast(name);
				EnsureBufferSpace(4);
				UNSAFE_WriteToBuffer_4_Float32(value);
			}
			else
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 32;
				UNSAFE_WriteToBuffer_4_Float32(value);
			}
		}

		public override void WriteString(string name, string value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 39;
				WriteStringFast(name);
			}
			else
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 40;
			}
			WriteStringFast(value);
		}

		public override void WriteUInt32(string name, uint value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 25;
				WriteStringFast(name);
				EnsureBufferSpace(4);
				UNSAFE_WriteToBuffer_4_UInt32(value);
			}
			else
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 26;
				UNSAFE_WriteToBuffer_4_UInt32(value);
			}
		}

		public override void WriteUInt64(string name, ulong value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 29;
				WriteStringFast(name);
				EnsureBufferSpace(8);
				UNSAFE_WriteToBuffer_8_UInt64(value);
			}
			else
			{
				EnsureBufferSpace(9);
				buffer[bufferIndex++] = 30;
				UNSAFE_WriteToBuffer_8_UInt64(value);
			}
		}

		public override void WriteUInt16(string name, ushort value)
		{
			if (name != null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 21;
				WriteStringFast(name);
				EnsureBufferSpace(2);
				UNSAFE_WriteToBuffer_2_UInt16(value);
			}
			else
			{
				EnsureBufferSpace(3);
				buffer[bufferIndex++] = 22;
				UNSAFE_WriteToBuffer_2_UInt16(value);
			}
		}

		public override void PrepareNewSerializationSession()
		{
			base.PrepareNewSerializationSession();
			types.Clear();
			bufferIndex = 0;
		}

		public override string GetDataDump()
		{
			if (!Stream.CanRead)
			{
				return "Binary data stream for writing cannot be read; cannot dump data.";
			}
			if (!Stream.CanSeek)
			{
				return "Binary data stream cannot seek; cannot dump data.";
			}
			FlushToStream();
			long position = Stream.Position;
			byte[] bytes = new byte[position];
			Stream.Position = 0L;
			Stream.Read(bytes, 0, (int)position);
			Stream.Position = position;
			return "Binary hex dump: " + ProperBitConverter.BytesToHexString(bytes);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void WriteType(Type type)
		{
			if (type == null)
			{
				EnsureBufferSpace(1);
				buffer[bufferIndex++] = 46;
				return;
			}
			if (types.TryGetValue(type, out var value))
			{
				EnsureBufferSpace(5);
				buffer[bufferIndex++] = 48;
				UNSAFE_WriteToBuffer_4_Int32(value);
				return;
			}
			value = types.Count;
			types.Add(type, value);
			EnsureBufferSpace(5);
			buffer[bufferIndex++] = 47;
			UNSAFE_WriteToBuffer_4_Int32(value);
			WriteStringFast(base.Context.Binder.BindToName(type, base.Context.Config.DebugContext));
		}

		private unsafe void WriteStringFast(string value)
		{
			bool flag = true;
			if (CompressStringsTo8BitWhenPossible)
			{
				flag = false;
				for (int i = 0; i < value.Length; i++)
				{
					if (value[i] > 'ÿ')
					{
						flag = true;
						break;
					}
				}
			}
			int num;
			if (flag)
			{
				num = value.Length * 2;
				if (TryEnsureBufferSpace(num + 5))
				{
					this.buffer[bufferIndex++] = 1;
					UNSAFE_WriteToBuffer_4_Int32(value.Length);
					if (BitConverter.IsLittleEndian)
					{
						fixed (byte* ptr = this.buffer)
						{
							fixed (char* ptr3 = value)
							{
								Struct256Bit* ptr2 = (Struct256Bit*)(ptr + bufferIndex);
								Struct256Bit* ptr4 = (Struct256Bit*)ptr3;
								byte* ptr5 = (byte*)ptr2 + num;
								while (ptr2 + 1 <= ptr5)
								{
									*(ptr2++) = *(ptr4++);
								}
								char* ptr6 = (char*)ptr2;
								char* ptr7 = (char*)ptr4;
								while (ptr6 < ptr5)
								{
									*(ptr6++) = *(ptr7++);
								}
							}
						}
					}
					else
					{
						fixed (byte* ptr8 = this.buffer)
						{
							fixed (char* ptr10 = value)
							{
								byte* ptr9 = ptr8 + bufferIndex;
								byte* ptr11 = (byte*)ptr10;
								for (int j = 0; j < num; j += 2)
								{
									*ptr9 = ptr11[1];
									ptr9[1] = *ptr11;
									ptr11 += 2;
									ptr9 += 2;
								}
							}
						}
					}
					bufferIndex += num;
					return;
				}
				FlushToStream();
				Stream.WriteByte(1);
				ProperBitConverter.GetBytes(small_buffer, 0, value.Length);
				Stream.Write(small_buffer, 0, 4);
				using Buffer<byte> buffer = Buffer<byte>.Claim(num);
				byte[] array = buffer.Array;
				UnsafeUtilities.StringToBytes(array, value, needs16BitSupport: true);
				Stream.Write(array, 0, num);
				return;
			}
			num = value.Length;
			if (TryEnsureBufferSpace(num + 5))
			{
				this.buffer[bufferIndex++] = 0;
				UNSAFE_WriteToBuffer_4_Int32(value.Length);
				for (int k = 0; k < num; k++)
				{
					this.buffer[bufferIndex++] = (byte)value[k];
				}
				return;
			}
			FlushToStream();
			Stream.WriteByte(0);
			ProperBitConverter.GetBytes(small_buffer, 0, value.Length);
			Stream.Write(small_buffer, 0, 4);
			using Buffer<byte> buffer2 = Buffer<byte>.Claim(value.Length);
			byte[] array2 = buffer2.Array;
			for (int l = 0; l < value.Length; l++)
			{
				array2[l] = (byte)value[l];
			}
			Stream.Write(array2, 0, value.Length);
		}

		public override void FlushToStream()
		{
			if (bufferIndex > 0)
			{
				Stream.Write(buffer, 0, bufferIndex);
				bufferIndex = 0;
			}
			base.FlushToStream();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_2_Char(char value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					*(char*)(ptr + bufferIndex) = value;
				}
				else
				{
					byte* ptr2 = ptr + bufferIndex;
					byte* ptr3 = (byte*)(&value) + 1;
					*(ptr2++) = *(ptr3--);
					*ptr2 = *ptr3;
				}
			}
			bufferIndex += 2;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_2_Int16(short value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					*(short*)(ptr + bufferIndex) = value;
				}
				else
				{
					byte* ptr2 = ptr + bufferIndex;
					byte* ptr3 = (byte*)(&value) + 1;
					*(ptr2++) = *(ptr3--);
					*ptr2 = *ptr3;
				}
			}
			bufferIndex += 2;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_2_UInt16(ushort value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					*(ushort*)(ptr + bufferIndex) = value;
				}
				else
				{
					byte* ptr2 = ptr + bufferIndex;
					byte* ptr3 = (byte*)(&value) + 1;
					*(ptr2++) = *(ptr3--);
					*ptr2 = *ptr3;
				}
			}
			bufferIndex += 2;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_4_Int32(int value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					*(int*)(ptr + bufferIndex) = value;
				}
				else
				{
					byte* ptr2 = ptr + bufferIndex;
					byte* ptr3 = (byte*)(&value) + 3;
					*(ptr2++) = *(ptr3--);
					*(ptr2++) = *(ptr3--);
					*(ptr2++) = *(ptr3--);
					*ptr2 = *ptr3;
				}
			}
			bufferIndex += 4;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_4_UInt32(uint value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					*(uint*)(ptr + bufferIndex) = value;
				}
				else
				{
					byte* ptr2 = ptr + bufferIndex;
					byte* ptr3 = (byte*)(&value) + 3;
					*(ptr2++) = *(ptr3--);
					*(ptr2++) = *(ptr3--);
					*(ptr2++) = *(ptr3--);
					*ptr2 = *ptr3;
				}
			}
			bufferIndex += 4;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_4_Float32(float value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(float*)(ptr + bufferIndex) = value;
					}
					else
					{
						byte* ptr2 = (byte*)(&value);
						byte* ptr3 = ptr + bufferIndex;
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value) + 3;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 4;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_8_Int64(long value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(long*)(ptr + bufferIndex) = value;
					}
					else
					{
						int* ptr2 = (int*)(&value);
						int* ptr3 = (int*)(ptr + bufferIndex);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value) + 7;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 8;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_8_UInt64(ulong value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(ulong*)(ptr + bufferIndex) = value;
					}
					else
					{
						int* ptr2 = (int*)(&value);
						int* ptr3 = (int*)(ptr + bufferIndex);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value) + 7;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 8;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_8_Float64(double value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(double*)(ptr + bufferIndex) = value;
					}
					else
					{
						int* ptr2 = (int*)(&value);
						int* ptr3 = (int*)(ptr + bufferIndex);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value) + 7;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 8;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_16_Decimal(decimal value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(decimal*)(ptr + bufferIndex) = value;
					}
					else
					{
						int* ptr2 = (int*)(&value);
						int* ptr3 = (int*)(ptr + bufferIndex);
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value) + 15;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 16;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe void UNSAFE_WriteToBuffer_16_Guid(Guid value)
		{
			fixed (byte* ptr = buffer)
			{
				if (BitConverter.IsLittleEndian)
				{
					if (ArchitectureInfo.Architecture_Supports_All_Unaligned_ReadWrites)
					{
						*(Guid*)(ptr + bufferIndex) = value;
					}
					else
					{
						int* ptr2 = (int*)(&value);
						int* ptr3 = (int*)(ptr + bufferIndex);
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*(ptr3++) = *(ptr2++);
						*ptr3 = *ptr2;
					}
				}
				else
				{
					byte* ptr4 = ptr + bufferIndex;
					byte* ptr5 = (byte*)(&value);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *(ptr5++);
					*(ptr4++) = *ptr5;
					ptr5 += 6;
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*(ptr4++) = *(ptr5--);
					*ptr4 = *ptr5;
				}
			}
			bufferIndex += 16;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void EnsureBufferSpace(int space)
		{
			int num = buffer.Length;
			if (space > num)
			{
				throw new Exception("Insufficient buffer capacity");
			}