// 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 { public static class BinaryReaderExtensions { /// /// Read an objects from a binary reader /// /// The element type for the array /// Reader to read data from /// Object instance. public static T ReadObject(this BinaryReader Reader) where T : class, IBinarySerializable { return (T)Activator.CreateInstance(typeof(T), Reader); } /// /// Read an array of strings from a binary reader /// /// Reader to read data from /// Array of strings, as serialized. May be null. public static string[] ReadStringArray(this BinaryReader Reader) { return Reader.ReadArray(() => Reader.ReadString()); } /// /// Read an array of objects from a binary reader /// /// The element type for the array /// Reader to read data from /// Array of objects, as serialized. May be null. public static T[] ReadArray(this BinaryReader Reader) where T : class, IBinarySerializable { return ReadArray(Reader, () => Reader.ReadObject()); } /// /// Read an array of objects from a binary reader /// /// The element type for the array /// Reader to read data from /// Delegate to call to serialize each element /// Array of objects, as serialized. May be null. public static T[] ReadArray(this BinaryReader Reader, Func ReadElement) { int NumItems = Reader.ReadInt32(); if(NumItems < 0) { return null; } T[] Items = new T[NumItems]; for(int Idx = 0; Idx < NumItems; Idx++) { Items[Idx] = ReadElement(); } return Items; } /// /// Read a list of strings from a binary reader /// /// Reader to read data from /// Array of strings, as serialized. May be null. public static List ReadStringList(this BinaryReader Reader) { return Reader.ReadList(() => Reader.ReadString()); } /// /// Read a list of objects from a binary reader /// /// The element type for the list /// Reader to read data from /// Delegate to call to serialize each element /// List of objects, as serialized. May be null. public static List ReadList(this BinaryReader Reader) where T : class, IBinarySerializable { return ReadList(Reader, () => Reader.ReadObject()); } /// /// Read a list of objects from a binary reader /// /// The element type for the list /// Reader to read data from /// Delegate to call to serialize each element /// List of objects, as serialized. May be null. public static List ReadList(this BinaryReader Reader, Func ReadElement) { int NumItems = Reader.ReadInt32(); if(NumItems < 0) { return null; } List Items = new List(NumItems); for(int Idx = 0; Idx < NumItems; Idx++) { Items.Add(ReadElement()); } return Items; } /// /// Read a list of objects from a binary reader /// /// The element type for the list /// Reader to read data from /// Delegate to call to serialize each key /// Delegate to call to serialize each value /// List of objects, as serialized. May be null. public static Dictionary ReadDictionary(this BinaryReader Reader, Func ReadKey, Func ReadValue) { int NumItems = Reader.ReadInt32(); if(NumItems < 0) { return null; } Dictionary Items = new Dictionary(NumItems); for(int Idx = 0; Idx < NumItems; Idx++) { K Key = ReadKey(); V Value = ReadValue(); Items.Add(Key, Value); } return Items; } /// /// 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 T ReadNullable(this BinaryReader Reader, Func ReadItem) where T : class { if(Reader.ReadBoolean()) { return ReadItem(); } else { return null; } } /// /// Reads a value of a specific type from a binary reader /// /// Reader for input data /// Type of value to read /// The value read from the stream public static object ReadObject(this BinaryReader Reader, Type ObjectType) { if(ObjectType == typeof(string)) { return Reader.ReadString(); } else if(ObjectType == typeof(bool)) { return Reader.ReadBoolean(); } else if(ObjectType == typeof(int)) { return Reader.ReadInt32(); } else if(ObjectType == typeof(float)) { return Reader.ReadSingle(); } else if(ObjectType == typeof(double)) { return Reader.ReadDouble(); } else if(ObjectType == typeof(string[])) { return Reader.ReadStringArray(); } else if(ObjectType == typeof(bool?)) { int Value = Reader.ReadInt32(); return (Value == -1)? (bool?)null : (Value == 0)? (bool?)false : (bool?)true; } else if(ObjectType.IsEnum) { return Enum.ToObject(ObjectType, Reader.ReadInt32()); } else { throw new Exception(String.Format("Reading binary objects of type '{0}' is not currently supported.", ObjectType.Name)); } } } }