using IPA.Config.Data;
using System;
namespace IPA.Config.Stores.Converters
{
///
/// A for objects normally serialized to config via .
///
/// the same type parameter that would be passed into
///
public class CustomObjectConverter : ValueConverter where T : class
{
private interface IImpl
{
T FromValue(Value value, object parent);
Value ToValue(T obj, object parent);
}
private class Impl : IImpl where U : class, GeneratedStoreImpl.IGeneratedStore, T
{
private static readonly GeneratedStoreImpl.GeneratedStoreCreator creator = GeneratedStoreImpl.GetCreator(typeof(T));
private static U Create(GeneratedStoreImpl.IGeneratedStore parent)
=> creator(parent) as U;
public T FromValue(Value value, object parent)
{ // lots of casting here, but it works i promise (probably) (parent can be a non-IGeneratedStore, however it won't necessarily behave then)
var obj = Create(parent as GeneratedStoreImpl.IGeneratedStore);
obj.Deserialize(value);
return obj;
}
public Value ToValue(T obj, object parent)
{
if (obj is GeneratedStoreImpl.IGeneratedStore store)
return store.Serialize();
else
{
var newObj = Create(null);
newObj.CopyFrom(obj, false); // don't use lock because it won't be used
return newObj.Serialize();
}
}
}
private static readonly IImpl impl = (IImpl)Activator.CreateInstance(
typeof(Impl<>).MakeGenericType(typeof(T), GeneratedStoreImpl.GetGeneratedType(typeof(T))));
///
/// Deserializes into a with the given .
///
/// the to deserialize
/// the parent object that will own the deserialized value
/// the deserialized value
///
public static T Deserialize(Value value, object parent)
=> impl.FromValue(value, parent);
///
/// Serializes into a structure, given .
///
/// the object to serialize
/// the parent object that owns
/// the tree that represents
///
public static Value Serialize(T obj, object parent)
=> impl.ToValue(obj, parent);
///
/// Deserializes into a with the given .
///
/// the to deserialize
/// the parent object that will own the deserialized value
/// the deserialized value
///
public override T FromValue(Value value, object parent)
=> Deserialize(value, parent);
///
/// Serializes into a structure, given .
///
/// the object to serialize
/// the parent object that owns
/// the tree that represents
///
public override Value ToValue(T obj, object parent)
=> Serialize(obj, parent);
}
///
/// A for custom value types, serialized identically to the reference types serialized with
/// .
///
/// the type of the value to convert
public class CustomValueTypeConverter : ValueConverter where T : struct
{
private static readonly GeneratedStoreImpl.SerializeObject serialize
= GeneratedStoreImpl.GetSerializerDelegate();
private static readonly GeneratedStoreImpl.DeserializeObject deserialize
= GeneratedStoreImpl.GetDeserializerDelegate();
///
/// Deserializes into a with the given .
///
/// the to deserialize
/// the parent object that will own the deserialized value
/// the deserialized value
///
public static T Deserialize(Value value, object parent)
=> deserialize(value, parent);
///
/// Serializes into a corresponding structure.
///
/// the object to serialize
/// the tree that represents
///
public static Value Serialize(T obj)
=> serialize(obj);
///
/// Deserializes into a with the given .
///
/// the to deserialize
/// the parent object that will own the deserialized value
/// the deserialized value
///
public override T FromValue(Value value, object parent)
=> Deserialize(value, parent);
///
/// Serializes into a structure, given .
///
/// the object to serialize
/// the parent object that owns
/// the tree that represents
///
public override Value ToValue(T obj, object parent)
=> Serialize(obj);
}
}