pixelgon/Assets/Source/Converters/fsForwardConverter.cs
2020-06-05 11:54:36 -07:00

86 lines
No EOL
3.2 KiB
C#

using System;
namespace FullSerializer {
/// <summary>
/// This allows you to forward serialization of an object to one of its members. For example,
///
/// [fsForward("Values")]
/// struct Wrapper {
/// public int[] Values;
/// }
///
/// Then `Wrapper` will be serialized into a JSON array of integers. It will be as if `Wrapper`
/// doesn't exist.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct)]
public sealed class fsForwardAttribute : Attribute {
/// <summary>
/// The name of the member we should serialize as.
/// </summary>
public string MemberName;
/// <summary>
/// Forward object serialization to an instance member. See class comment.
/// </summary>
/// <param name="memberName">The name of the member that we should serialize this object as.</param>
public fsForwardAttribute(string memberName) {
MemberName = memberName;
}
}
}
namespace FullSerializer.Internal {
public class fsForwardConverter : fsConverter {
private string _memberName;
public fsForwardConverter(fsForwardAttribute attribute) {
_memberName = attribute.MemberName;
}
public override bool CanProcess(Type type) {
throw new NotSupportedException("Please use the [fsForward(...)] attribute.");
}
private fsResult GetProperty(object instance, out fsMetaProperty property) {
var properties = fsMetaType.Get(Serializer.Config, instance.GetType()).Properties;
for (int i = 0; i < properties.Length; ++i) {
if (properties[i].MemberName == _memberName) {
property = properties[i];
return fsResult.Success;
}
}
property = default(fsMetaProperty);
return fsResult.Fail("No property named \"" + _memberName + "\" on " + instance.GetType().CSharpName());
}
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
serialized = fsData.Null;
var result = fsResult.Success;
fsMetaProperty property;
if ((result += GetProperty(instance, out property)).Failed) return result;
var actualInstance = property.Read(instance);
return Serializer.TrySerialize(property.StorageType, actualInstance, out serialized);
}
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
var result = fsResult.Success;
fsMetaProperty property;
if ((result += GetProperty(instance, out property)).Failed) return result;
object actualInstance = null;
if ((result += Serializer.TryDeserialize(data, property.StorageType, ref actualInstance)).Failed)
return result;
property.Write(instance, actualInstance);
return result;
}
public override object CreateInstance(fsData data, Type storageType) {
return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
}
}
}