// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; namespace EpicGames.Core { /// /// Extension methods for /// 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 /// 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 /// /// Dictionary key type /// Dictionary value type /// 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) where TKey : notnull { int numItems = reader.ReadInt32(); if (numItems < 0) { return null; } Dictionary items = new Dictionary(numItems); for (int idx = 0; idx < numItems; idx++) { TKey key = readKey(); TValue 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 == typeof(FileReference)) { return reader.ReadFileReference(); } 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)); } } } }