// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Tools.DotNETCommon { /// /// Interface that can be implemented by objects to support BinaryWriter container functionality. Also implies that /// derived objects will have a constructor taking a single BinaryReader argument (similar to how the system ISerializable /// interface assumes a specific constructor) /// public interface IBinarySerializable { void Write(BinaryWriter Writer); } /// /// Extension methods for BinaryWriter class /// public static class BinaryWriterExtensions { /// /// Writes an item implementing the IBinarySerializable interface to a binary writer. Included for symmetry with standard Writer.Write(X) calls. /// /// Writer to serialize to /// The item to write public static void Write(this BinaryWriter Writer, IBinarySerializable Item) { Item.Write(Writer); } /// /// Writes an array of strings to a binary writer. /// /// Writer to serialize to /// Array of items public static void Write(this BinaryWriter Writer, string[] Items) { Write(Writer, Items, Item => Writer.Write(Item)); } /// /// Writes an array to a binary writer. /// /// The array element type /// Writer to serialize to /// Array of items public static void Write(this BinaryWriter Writer, T[] Items) where T : class, IBinarySerializable { Write(Writer, Items, Item => Writer.Write(Item)); } /// /// Writes an array to a binary writer. /// /// The array element type /// Writer to serialize to /// Array of items /// Delegate to call to serialize each element public static void Write(this BinaryWriter Writer, T[] Items, Action WriteElement) { if(Items == null) { Writer.Write(-1); } else { Writer.Write(Items.Length); for(int Idx = 0; Idx < Items.Length; Idx++) { WriteElement(Items[Idx]); } } } /// /// Writes a list of strings to a binary writer. /// /// Writer to serialize to /// Array of items public static void Write(this BinaryWriter Writer, List Items) { Write(Writer, Items, Item => Writer.Write(Item)); } /// /// Writes a list to a binary writer. /// /// The array element type /// Writer to serialize to /// Array of items public static void Write(this BinaryWriter Writer, List Items) where T : class, IBinarySerializable { Write(Writer, Items, Item => Writer.Write(Item)); } /// /// Writes a list to a binary writer. /// /// The list element type /// Writer to serialize to /// List of items /// Delegate to call to serialize each element public static void Write(this BinaryWriter Writer, List Items, Action WriteElement) { if (Items == null) { Writer.Write(-1); } else { Writer.Write(Items.Count); for (int Idx = 0; Idx < Items.Count; Idx++) { WriteElement(Items[Idx]); } } } /// /// Write a dictionary to a binary writer /// /// The key type for the dictionary /// The value type for the dictionary /// Reader to read data from /// List of items to be written /// Delegate to call to serialize each key /// Delegate to call to serialize each value /// Dictionary of objects, as serialized. May be null. public static void Write(this BinaryWriter Writer, Dictionary Items, Action WriteKey, Action WriteValue) { if(Items == null) { Writer.Write(-1); } else { Writer.Write(Items.Count); foreach(KeyValuePair Item in Items) { WriteKey(Item.Key); WriteValue(Item.Value); } } } /// /// Read a nullable object from a binary reader /// /// Type of the object /// Reader to read data from /// Function to read the payload, if non-null /// Object instance or null public static void WriteNullable(this BinaryWriter Writer, T Item, Action WriteItem) where T : class { if(Item == null) { Writer.Write(false); } else { Writer.Write(true); WriteItem(); } } /// /// Writes a value of a specific type to a binary writer /// /// Writer for output data /// Type of value to write /// The value to output public static void Write(this BinaryWriter Writer, Type FieldType, object Value) { if(FieldType == typeof(string)) { Writer.Write((string)Value); } else if(FieldType == typeof(bool)) { Writer.Write((bool)Value); } else if(FieldType == typeof(int)) { Writer.Write((int)Value); } else if(FieldType == typeof(float)) { Writer.Write((float)Value); } else if(FieldType == typeof(double)) { Writer.Write((double)Value); } else if(FieldType.IsEnum) { Writer.Write((int)Value); } else if(FieldType == typeof(string[])) { Writer.Write((string[])Value); } else if(FieldType == typeof(bool?)) { bool? NullableValue = (bool?)Value; Writer.Write(NullableValue.HasValue? NullableValue.Value? 1 : 0 : -1); } else { throw new Exception(String.Format("Unsupported type '{0}' for binary serialization", FieldType.Name)); } } } }