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