using System.Collections.Generic; using System.Collections; using System.IO; using System; using UnityEngine; using System.Text; using System.Globalization; using ES3Types; namespace ES3Internal { internal class ES3BinaryWriter : ES3Writer { internal BinaryWriter baseWriter; public ES3BinaryWriter(Stream stream, ES3Settings settings) : this(stream, settings, true, true){} internal ES3BinaryWriter(Stream stream, ES3Settings settings, bool writeHeaderAndFooter, bool mergeKeys) : base(settings, writeHeaderAndFooter, mergeKeys) { baseWriter = new BinaryWriter(stream, settings.encoding); StartWriteFile(); } internal override void Write(string key, Type type, byte[] value) { StartWriteProperty(key); using (var ms = new MemoryStream()) { using (var writer = ES3Writer.Create(ms, new ES3Settings(ES3.EncryptionType.None, ES3.CompressionType.None, ES3.Format.Binary_Alpha), false, false)) { writer.StartWriteObject(key); writer.WriteType(type); writer.WriteRawProperty("value", value); writer.EndWriteObject(key); } var bytes = ms.ToArray(); Write7BitEncodedInt(bytes.Length); baseWriter.Write(bytes); } EndWriteProperty(key); } /// Writes a value to the writer with the given key, using the given type rather than the generic parameter. /// The key which uniquely identifies this value. /// The value we want to write. /// The type we want to use for the header, and to retrieve an ES3Type. [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public override void Write(Type type, string key, object value) { StartWriteProperty(key); using (var ms = new MemoryStream()) { using (var writer = ES3Writer.Create(ms, new ES3Settings(ES3.EncryptionType.None, ES3.CompressionType.None, ES3.Format.Binary_Alpha), false, false)) { writer.StartWriteObject(key); writer.WriteType(type); writer.WriteProperty("value", value, ES3TypeMgr.GetOrCreateES3Type(type), settings.referenceMode); writer.EndWriteObject(key); } var bytes = ms.ToArray(); Write7BitEncodedInt(bytes.Length); baseWriter.Write(bytes); } EndWriteProperty(key); MarkKeyForDeletion(key); } /// Writes a field or property to the writer. Note that this should only be called within an ES3Type. /// The name of the field or property. /// The value we want to write. /// Whether we want to write the property by reference, by value, or both. public override void WriteProperty(string name, object value, ES3.ReferenceMode memberReferenceMode) { if (SerializationDepthLimitExceeded()) return; StartWriteProperty(name); using (var ms = new MemoryStream()) { using (var writer = ES3Writer.Create(ms, new ES3Settings(ES3.EncryptionType.None, ES3.CompressionType.None, ES3.Format.Binary_Alpha), false, false)) { writer.Write(value, memberReferenceMode); } var bytes = ms.ToArray(); Write7BitEncodedInt(bytes.Length); baseWriter.Write(bytes); } EndWriteProperty(name); } [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public override void WriteProperty(string name, object value, ES3Type type, ES3.ReferenceMode memberReferenceMode) { if (SerializationDepthLimitExceeded()) return; StartWriteProperty(name); using (var ms = new MemoryStream()) { using (var writer = ES3Writer.Create(ms, new ES3Settings(ES3.EncryptionType.None, ES3.CompressionType.None, ES3.Format.Binary_Alpha), false, false)) { writer.Write(value, type, memberReferenceMode); } var bytes = ms.ToArray(); Write7BitEncodedInt(bytes.Length); baseWriter.Write(bytes); } EndWriteProperty(name); } [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public override void WritePropertyByRef(string name, UnityEngine.Object value) { if (SerializationDepthLimitExceeded()) return; StartWriteProperty(name); using (var ms = new MemoryStream()) { using (var writer = ES3Writer.Create(ms, new ES3Settings(ES3.EncryptionType.None, ES3.CompressionType.None, ES3.Format.Binary_Alpha), false, false)) { if (value == null) { WriteNull(); return; }; writer.StartWriteObject(name); writer.WriteRef(value); writer.EndWriteObject(name); } var bytes = ms.ToArray(); Write7BitEncodedInt(bytes.Length); baseWriter.Write(bytes); } EndWriteProperty(name); } #region WritePrimitive(value) methods. internal override void WritePrimitive(int value) { baseWriter.Write((byte)ES3SpecialByte.Int); Write7BitEncodedInt(value); } internal override void WritePrimitive(float value) { baseWriter.Write((byte)ES3SpecialByte.Float); baseWriter.Write(value); } internal override void WritePrimitive(bool value) { baseWriter.Write((byte)ES3SpecialByte.Bool); baseWriter.Write(value); } internal override void WritePrimitive(decimal value) { baseWriter.Write((byte)ES3SpecialByte.Decimal); baseWriter.Write(value); } internal override void WritePrimitive(double value) { baseWriter.Write((byte)ES3SpecialByte.Double); baseWriter.Write(value); } internal override void WritePrimitive(long value) { baseWriter.Write((byte)ES3SpecialByte.Long); baseWriter.Write(value); } internal override void WritePrimitive(ulong value) { baseWriter.Write((byte)ES3SpecialByte.Ulong); baseWriter.Write(value); } internal override void WritePrimitive(uint value) { baseWriter.Write((byte)ES3SpecialByte.Uint); baseWriter.Write(value); } internal override void WritePrimitive(byte value) { baseWriter.Write((byte)ES3SpecialByte.Byte); baseWriter.Write(value); } internal override void WritePrimitive(sbyte value) { baseWriter.Write((byte)ES3SpecialByte.Sbyte); baseWriter.Write(value); } internal override void WritePrimitive(short value) { baseWriter.Write((byte)ES3SpecialByte.Short); baseWriter.Write(value); } internal override void WritePrimitive(ushort value) { baseWriter.Write((byte)ES3SpecialByte.Ushort); baseWriter.Write(value); } internal override void WritePrimitive(char value) { baseWriter.Write((byte)ES3SpecialByte.Char); baseWriter.Write(value); } internal override void WritePrimitive(byte[] value) { baseWriter.Write((byte)ES3SpecialByte.ByteArray); baseWriter.Write(value.Length); baseWriter.Write(value); } internal override void WritePrimitive(string value) { baseWriter.Write((byte)ES3SpecialByte.String); baseWriter.Write(value); } private void Write7BitEncodedInt(int value) { // Write out an int 7 bits at a time. The high bit of the byte, // when on, tells reader to continue reading more bytes. uint v = (uint)value; // support negative numbers while (v >= 0x80) { baseWriter.Write((byte)(v | 0x80)); v >>= 7; } baseWriter.Write((byte)v); } internal override void WriteNull() { baseWriter.Write((byte)ES3SpecialByte.Null); } #endregion #region Overridden methods internal override void WriteRawProperty(string name, byte[] value) { StartWriteProperty(name); Write7BitEncodedInt(value.Length); baseWriter.Write(value); EndWriteProperty(name); } // File internal override void StartWriteFile() { base.StartWriteFile(); } internal override void EndWriteFile() { baseWriter.Write(ES3Binary.ObjectTerminator); base.EndWriteFile(); } // Property internal override void StartWriteProperty(string name) { base.StartWriteProperty(name); baseWriter.Write(name); } internal override void EndWriteProperty(string name) { base.EndWriteProperty(name); } // Object internal override void StartWriteObject(string name) { base.StartWriteObject(name); baseWriter.Write((byte)ES3SpecialByte.Object); } internal override void EndWriteObject(string name) { baseWriter.Write(ES3Binary.ObjectTerminator); base.EndWriteObject(name); } // Collection internal override void StartWriteCollection() { base.StartWriteCollection(); baseWriter.Write((byte)ES3SpecialByte.Collection); } internal override void EndWriteCollection() { baseWriter.Write((byte)ES3SpecialByte.Terminator); base.EndWriteCollection(); } internal override void StartWriteCollectionItem(int index){} internal override void EndWriteCollectionItem(int index) { baseWriter.Write((byte)ES3SpecialByte.CollectionItem); } // Dictionary internal override void StartWriteDictionary() { StartWriteObject(null); baseWriter.Write((byte)ES3SpecialByte.Dictionary); } internal override void EndWriteDictionary() { baseWriter.Write((byte)ES3SpecialByte.Terminator); EndWriteObject(null); } internal override void StartWriteDictionaryKey(int index){} internal override void EndWriteDictionaryKey(int index){} internal override void StartWriteDictionaryValue(int index){} internal override void EndWriteDictionaryValue(int index){} #endregion #region Binary-specific methods #endregion public override void Dispose() { #if NETFX_CORE baseWriter.Dispose(); #else baseWriter.Close(); #endif } } }