// 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));
}
}
}
}