removed an unused serialization library
This commit is contained in:
parent
cbfd462269
commit
270428dc0e
108 changed files with 0 additions and 6794 deletions
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1b1ed4807593b5042b522b04c705a36c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c9b1df9bbef7286479721c8d6f6f5a72
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,47 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.AnimationCurve_DirectConverter Register_AnimationCurve_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class AnimationCurve_DirectConverter : fsDirectConverter<AnimationCurve> {
|
||||
protected override fsResult DoSerialize(AnimationCurve model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "keys", model.keys);
|
||||
result += SerializeMember(serialized, null, "preWrapMode", model.preWrapMode);
|
||||
result += SerializeMember(serialized, null, "postWrapMode", model.postWrapMode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref AnimationCurve model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.keys;
|
||||
result += DeserializeMember(data, null, "keys", out t0);
|
||||
model.keys = t0;
|
||||
|
||||
var t1 = model.preWrapMode;
|
||||
result += DeserializeMember(data, null, "preWrapMode", out t1);
|
||||
model.preWrapMode = t1;
|
||||
|
||||
var t2 = model.postWrapMode;
|
||||
result += DeserializeMember(data, null, "postWrapMode", out t2);
|
||||
model.postWrapMode = t2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new AnimationCurve();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2476f8660fdb77f4cbe97b4c53e760fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,42 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.Bounds_DirectConverter Register_Bounds_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class Bounds_DirectConverter : fsDirectConverter<Bounds> {
|
||||
protected override fsResult DoSerialize(Bounds model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "center", model.center);
|
||||
result += SerializeMember(serialized, null, "size", model.size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Bounds model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.center;
|
||||
result += DeserializeMember(data, null, "center", out t0);
|
||||
model.center = t0;
|
||||
|
||||
var t1 = model.size;
|
||||
result += DeserializeMember(data, null, "size", out t1);
|
||||
model.size = t1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new Bounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 891b0567146e2334b880d3a41f3c26f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,42 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.GUIStyleState_DirectConverter Register_GUIStyleState_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class GUIStyleState_DirectConverter : fsDirectConverter<GUIStyleState> {
|
||||
protected override fsResult DoSerialize(GUIStyleState model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "background", model.background);
|
||||
result += SerializeMember(serialized, null, "textColor", model.textColor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref GUIStyleState model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.background;
|
||||
result += DeserializeMember(data, null, "background", out t0);
|
||||
model.background = t0;
|
||||
|
||||
var t2 = model.textColor;
|
||||
result += DeserializeMember(data, null, "textColor", out t2);
|
||||
model.textColor = t2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new GUIStyleState();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dd89cb6fc1667534fb89879ab916ad17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,162 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.GUIStyle_DirectConverter Register_GUIStyle_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class GUIStyle_DirectConverter : fsDirectConverter<GUIStyle> {
|
||||
protected override fsResult DoSerialize(GUIStyle model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "active", model.active);
|
||||
result += SerializeMember(serialized, null, "alignment", model.alignment);
|
||||
result += SerializeMember(serialized, null, "border", model.border);
|
||||
result += SerializeMember(serialized, null, "clipping", model.clipping);
|
||||
result += SerializeMember(serialized, null, "contentOffset", model.contentOffset);
|
||||
result += SerializeMember(serialized, null, "fixedHeight", model.fixedHeight);
|
||||
result += SerializeMember(serialized, null, "fixedWidth", model.fixedWidth);
|
||||
result += SerializeMember(serialized, null, "focused", model.focused);
|
||||
result += SerializeMember(serialized, null, "font", model.font);
|
||||
result += SerializeMember(serialized, null, "fontSize", model.fontSize);
|
||||
result += SerializeMember(serialized, null, "fontStyle", model.fontStyle);
|
||||
result += SerializeMember(serialized, null, "hover", model.hover);
|
||||
result += SerializeMember(serialized, null, "imagePosition", model.imagePosition);
|
||||
result += SerializeMember(serialized, null, "margin", model.margin);
|
||||
result += SerializeMember(serialized, null, "name", model.name);
|
||||
result += SerializeMember(serialized, null, "normal", model.normal);
|
||||
result += SerializeMember(serialized, null, "onActive", model.onActive);
|
||||
result += SerializeMember(serialized, null, "onFocused", model.onFocused);
|
||||
result += SerializeMember(serialized, null, "onHover", model.onHover);
|
||||
result += SerializeMember(serialized, null, "onNormal", model.onNormal);
|
||||
result += SerializeMember(serialized, null, "overflow", model.overflow);
|
||||
result += SerializeMember(serialized, null, "padding", model.padding);
|
||||
result += SerializeMember(serialized, null, "richText", model.richText);
|
||||
result += SerializeMember(serialized, null, "stretchHeight", model.stretchHeight);
|
||||
result += SerializeMember(serialized, null, "stretchWidth", model.stretchWidth);
|
||||
result += SerializeMember(serialized, null, "wordWrap", model.wordWrap);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref GUIStyle model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.active;
|
||||
result += DeserializeMember(data, null, "active", out t0);
|
||||
model.active = t0;
|
||||
|
||||
var t2 = model.alignment;
|
||||
result += DeserializeMember(data, null, "alignment", out t2);
|
||||
model.alignment = t2;
|
||||
|
||||
var t3 = model.border;
|
||||
result += DeserializeMember(data, null, "border", out t3);
|
||||
model.border = t3;
|
||||
|
||||
var t4 = model.clipping;
|
||||
result += DeserializeMember(data, null, "clipping", out t4);
|
||||
model.clipping = t4;
|
||||
|
||||
var t5 = model.contentOffset;
|
||||
result += DeserializeMember(data, null, "contentOffset", out t5);
|
||||
model.contentOffset = t5;
|
||||
|
||||
var t6 = model.fixedHeight;
|
||||
result += DeserializeMember(data, null, "fixedHeight", out t6);
|
||||
model.fixedHeight = t6;
|
||||
|
||||
var t7 = model.fixedWidth;
|
||||
result += DeserializeMember(data, null, "fixedWidth", out t7);
|
||||
model.fixedWidth = t7;
|
||||
|
||||
var t8 = model.focused;
|
||||
result += DeserializeMember(data, null, "focused", out t8);
|
||||
model.focused = t8;
|
||||
|
||||
var t9 = model.font;
|
||||
result += DeserializeMember(data, null, "font", out t9);
|
||||
model.font = t9;
|
||||
|
||||
var t10 = model.fontSize;
|
||||
result += DeserializeMember(data, null, "fontSize", out t10);
|
||||
model.fontSize = t10;
|
||||
|
||||
var t11 = model.fontStyle;
|
||||
result += DeserializeMember(data, null, "fontStyle", out t11);
|
||||
model.fontStyle = t11;
|
||||
|
||||
var t12 = model.hover;
|
||||
result += DeserializeMember(data, null, "hover", out t12);
|
||||
model.hover = t12;
|
||||
|
||||
var t13 = model.imagePosition;
|
||||
result += DeserializeMember(data, null, "imagePosition", out t13);
|
||||
model.imagePosition = t13;
|
||||
|
||||
var t16 = model.margin;
|
||||
result += DeserializeMember(data, null, "margin", out t16);
|
||||
model.margin = t16;
|
||||
|
||||
var t17 = model.name;
|
||||
result += DeserializeMember(data, null, "name", out t17);
|
||||
model.name = t17;
|
||||
|
||||
var t18 = model.normal;
|
||||
result += DeserializeMember(data, null, "normal", out t18);
|
||||
model.normal = t18;
|
||||
|
||||
var t19 = model.onActive;
|
||||
result += DeserializeMember(data, null, "onActive", out t19);
|
||||
model.onActive = t19;
|
||||
|
||||
var t20 = model.onFocused;
|
||||
result += DeserializeMember(data, null, "onFocused", out t20);
|
||||
model.onFocused = t20;
|
||||
|
||||
var t21 = model.onHover;
|
||||
result += DeserializeMember(data, null, "onHover", out t21);
|
||||
model.onHover = t21;
|
||||
|
||||
var t22 = model.onNormal;
|
||||
result += DeserializeMember(data, null, "onNormal", out t22);
|
||||
model.onNormal = t22;
|
||||
|
||||
var t23 = model.overflow;
|
||||
result += DeserializeMember(data, null, "overflow", out t23);
|
||||
model.overflow = t23;
|
||||
|
||||
var t24 = model.padding;
|
||||
result += DeserializeMember(data, null, "padding", out t24);
|
||||
model.padding = t24;
|
||||
|
||||
var t25 = model.richText;
|
||||
result += DeserializeMember(data, null, "richText", out t25);
|
||||
model.richText = t25;
|
||||
|
||||
var t26 = model.stretchHeight;
|
||||
result += DeserializeMember(data, null, "stretchHeight", out t26);
|
||||
model.stretchHeight = t26;
|
||||
|
||||
var t27 = model.stretchWidth;
|
||||
result += DeserializeMember(data, null, "stretchWidth", out t27);
|
||||
model.stretchWidth = t27;
|
||||
|
||||
var t28 = model.wordWrap;
|
||||
result += DeserializeMember(data, null, "wordWrap", out t28);
|
||||
model.wordWrap = t28;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new GUIStyle();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49fa198b11ff8fe4d96d54ab58be73fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,42 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.Gradient_DirectConverter Register_Gradient_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class Gradient_DirectConverter : fsDirectConverter<Gradient> {
|
||||
protected override fsResult DoSerialize(Gradient model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "alphaKeys", model.alphaKeys);
|
||||
result += SerializeMember(serialized, null, "colorKeys", model.colorKeys);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Gradient model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.alphaKeys;
|
||||
result += DeserializeMember(data, null, "alphaKeys", out t0);
|
||||
model.alphaKeys = t0;
|
||||
|
||||
var t1 = model.colorKeys;
|
||||
result += DeserializeMember(data, null, "colorKeys", out t1);
|
||||
model.colorKeys = t1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new Gradient();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bdeec5510c4eaad4fa61e836562c3d45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,52 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.Keyframe_DirectConverter Register_Keyframe_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class Keyframe_DirectConverter : fsDirectConverter<Keyframe> {
|
||||
protected override fsResult DoSerialize(Keyframe model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "time", model.time);
|
||||
result += SerializeMember(serialized, null, "value", model.value);
|
||||
result += SerializeMember(serialized, null, "inTangent", model.inTangent);
|
||||
result += SerializeMember(serialized, null, "outTangent", model.outTangent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Keyframe model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.time;
|
||||
result += DeserializeMember(data, null, "time", out t0);
|
||||
model.time = t0;
|
||||
|
||||
var t1 = model.value;
|
||||
result += DeserializeMember(data, null, "value", out t1);
|
||||
model.value = t1;
|
||||
|
||||
var t3 = model.inTangent;
|
||||
result += DeserializeMember(data, null, "inTangent", out t3);
|
||||
model.inTangent = t3;
|
||||
|
||||
var t4 = model.outTangent;
|
||||
result += DeserializeMember(data, null, "outTangent", out t4);
|
||||
model.outTangent = t4;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new Keyframe();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3ff33c51e3301d44b8d70f16d1eb169
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,37 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.LayerMask_DirectConverter Register_LayerMask_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class LayerMask_DirectConverter : fsDirectConverter<LayerMask> {
|
||||
protected override fsResult DoSerialize(LayerMask model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "value", model.value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref LayerMask model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.value;
|
||||
result += DeserializeMember(data, null, "value", out t0);
|
||||
model.value = t0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new LayerMask();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6ba002c4a5beab644b8b40ecc769956c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,52 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.RectOffset_DirectConverter Register_RectOffset_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class RectOffset_DirectConverter : fsDirectConverter<RectOffset> {
|
||||
protected override fsResult DoSerialize(RectOffset model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "bottom", model.bottom);
|
||||
result += SerializeMember(serialized, null, "left", model.left);
|
||||
result += SerializeMember(serialized, null, "right", model.right);
|
||||
result += SerializeMember(serialized, null, "top", model.top);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref RectOffset model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.bottom;
|
||||
result += DeserializeMember(data, null, "bottom", out t0);
|
||||
model.bottom = t0;
|
||||
|
||||
var t2 = model.left;
|
||||
result += DeserializeMember(data, null, "left", out t2);
|
||||
model.left = t2;
|
||||
|
||||
var t3 = model.right;
|
||||
result += DeserializeMember(data, null, "right", out t3);
|
||||
model.right = t3;
|
||||
|
||||
var t4 = model.top;
|
||||
result += DeserializeMember(data, null, "top", out t4);
|
||||
model.top = t4;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new RectOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c677229cfd3fa6b4690b364b9529fc9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,52 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.DirectConverters.Rect_DirectConverter Register_Rect_DirectConverter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.DirectConverters {
|
||||
public class Rect_DirectConverter : fsDirectConverter<Rect> {
|
||||
protected override fsResult DoSerialize(Rect model, Dictionary<string, fsData> serialized) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
result += SerializeMember(serialized, null, "xMin", model.xMin);
|
||||
result += SerializeMember(serialized, null, "yMin", model.yMin);
|
||||
result += SerializeMember(serialized, null, "xMax", model.xMax);
|
||||
result += SerializeMember(serialized, null, "yMax", model.yMax);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Rect model) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
var t0 = model.xMin;
|
||||
result += DeserializeMember(data, null, "xMin", out t0);
|
||||
model.xMin = t0;
|
||||
|
||||
var t1 = model.yMin;
|
||||
result += DeserializeMember(data, null, "yMin", out t1);
|
||||
model.yMin = t1;
|
||||
|
||||
var t2 = model.xMax;
|
||||
result += DeserializeMember(data, null, "xMax", out t2);
|
||||
model.xMax = t2;
|
||||
|
||||
var t3 = model.yMax;
|
||||
result += DeserializeMember(data, null, "yMax", out t3);
|
||||
model.yMax = t3;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new Rect();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c430350334bb384791e23b7f1b5bf9d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,42 +0,0 @@
|
|||
#if !NO_UNITY
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace FullSerializer {
|
||||
partial class fsConverterRegistrar {
|
||||
public static Internal.Converters.UnityEvent_Converter Register_UnityEvent_Converter;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal.Converters {
|
||||
// The standard FS reflection converter has started causing Unity to crash when processing
|
||||
// UnityEvent. We can send the serialization through JsonUtility which appears to work correctly
|
||||
// instead.
|
||||
//
|
||||
// We have to support legacy serialization formats so importing works as expected.
|
||||
public class UnityEvent_Converter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return typeof(UnityEvent).Resolve().IsAssignableFrom(type) && type.IsGenericType == false;
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
Type objectType = (Type)instance;
|
||||
|
||||
fsResult result = fsResult.Success;
|
||||
instance = JsonUtility.FromJson(fsJsonPrinter.CompressedJson(data), objectType);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
fsResult result = fsResult.Success;
|
||||
serialized = fsJsonParser.Parse(JsonUtility.ToJson(instance));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 45faf466f4f7d9c45b3f35d23689c56a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,80 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsArrayConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return type.IsArray;
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
// note: IList[index] is **significantly** faster than Array.Get, so make sure we use
|
||||
// that instead.
|
||||
|
||||
IList arr = (Array)instance;
|
||||
Type elementType = storageType.GetElementType();
|
||||
|
||||
var result = fsResult.Success;
|
||||
|
||||
serialized = fsData.CreateList(arr.Count);
|
||||
var serializedList = serialized.AsList;
|
||||
|
||||
for (int i = 0; i < arr.Count; ++i) {
|
||||
object item = arr[i];
|
||||
|
||||
fsData serializedItem;
|
||||
|
||||
var itemResult = Serializer.TrySerialize(elementType, item, out serializedItem);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) continue;
|
||||
|
||||
serializedList.Add(serializedItem);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
// Verify that we actually have an List
|
||||
if ((result += CheckType(data, fsDataType.Array)).Failed) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Type elementType = storageType.GetElementType();
|
||||
|
||||
var serializedList = data.AsList;
|
||||
var list = new ArrayList(serializedList.Count);
|
||||
int existingCount = list.Count;
|
||||
|
||||
for (int i = 0; i < serializedList.Count; ++i) {
|
||||
var serializedItem = serializedList[i];
|
||||
object deserialized = null;
|
||||
if (i < existingCount) deserialized = list[i];
|
||||
|
||||
var itemResult = Serializer.TryDeserialize(serializedItem, elementType, ref deserialized);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) continue;
|
||||
|
||||
if (i < existingCount) list[i] = deserialized;
|
||||
else list.Add(deserialized);
|
||||
}
|
||||
|
||||
instance = list.ToArray(elementType);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff26f497131ae3b4db5c02bf6ad36cbc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,96 +0,0 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Supports serialization for DateTime, DateTimeOffset, and TimeSpan.
|
||||
/// </summary>
|
||||
public class fsDateConverter : fsConverter {
|
||||
// The format strings that we use when serializing DateTime and DateTimeOffset types.
|
||||
private const string DefaultDateTimeFormatString = @"o";
|
||||
private const string DateTimeOffsetFormatString = @"o";
|
||||
|
||||
private string DateTimeFormatString {
|
||||
get {
|
||||
return Serializer.Config.CustomDateTimeFormatString ?? DefaultDateTimeFormatString;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanProcess(Type type) {
|
||||
return
|
||||
type == typeof(DateTime) ||
|
||||
type == typeof(DateTimeOffset) ||
|
||||
type == typeof(TimeSpan);
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
if (instance is DateTime) {
|
||||
var dateTime = (DateTime)instance;
|
||||
serialized = new fsData(dateTime.ToString(DateTimeFormatString));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (instance is DateTimeOffset) {
|
||||
var dateTimeOffset = (DateTimeOffset)instance;
|
||||
serialized = new fsData(dateTimeOffset.ToString(DateTimeOffsetFormatString));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (instance is TimeSpan) {
|
||||
var timeSpan = (TimeSpan)instance;
|
||||
serialized = new fsData(timeSpan.ToString());
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("FullSerializer Internal Error -- Unexpected serialization type");
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
if (data.IsString == false) {
|
||||
return fsResult.Fail("Date deserialization requires a string, not " + data.Type);
|
||||
}
|
||||
|
||||
if (storageType == typeof(DateTime)) {
|
||||
DateTime result;
|
||||
if (DateTime.TryParse(data.AsString, null, DateTimeStyles.RoundtripKind, out result)) {
|
||||
instance = result;
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
// DateTime.TryParse can fail for some valid DateTime instances. Try to use Convert.ToDateTime.
|
||||
if (fsGlobalConfig.AllowInternalExceptions) {
|
||||
try {
|
||||
instance = Convert.ToDateTime(data.AsString);
|
||||
return fsResult.Success;
|
||||
} catch (Exception e) {
|
||||
return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTime; got exception " + e);
|
||||
}
|
||||
}
|
||||
|
||||
return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTime");
|
||||
}
|
||||
|
||||
if (storageType == typeof(DateTimeOffset)) {
|
||||
DateTimeOffset result;
|
||||
if (DateTimeOffset.TryParse(data.AsString, null, DateTimeStyles.RoundtripKind, out result)) {
|
||||
instance = result;
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTimeOffset");
|
||||
}
|
||||
|
||||
if (storageType == typeof(TimeSpan)) {
|
||||
TimeSpan result;
|
||||
if (TimeSpan.TryParse(data.AsString, out result)) {
|
||||
instance = result;
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
return fsResult.Fail("Unable to parse " + data.AsString + " into a TimeSpan");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("FullSerializer Internal Error -- Unexpected deserialization type");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3dcd313c5acdc442a22f755080c67a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,171 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
// While the generic IEnumerable converter can handle dictionaries, we process them separately here because
|
||||
// we support a few more advanced use-cases with dictionaries, such as inline strings. Further, dictionary
|
||||
// processing in general is a bit more advanced because a few of the collection implementations are buggy.
|
||||
public class fsDictionaryConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return typeof(IDictionary).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance_, Type storageType) {
|
||||
var instance = (IDictionary)instance_;
|
||||
var result = fsResult.Success;
|
||||
|
||||
Type keyStorageType, valueStorageType;
|
||||
GetKeyValueTypes(instance.GetType(), out keyStorageType, out valueStorageType);
|
||||
|
||||
if (data.IsList) {
|
||||
var list = data.AsList;
|
||||
for (int i = 0; i < list.Count; ++i) {
|
||||
var item = list[i];
|
||||
|
||||
fsData keyData, valueData;
|
||||
if ((result += CheckType(item, fsDataType.Object)).Failed) return result;
|
||||
if ((result += CheckKey(item, "Key", out keyData)).Failed) return result;
|
||||
if ((result += CheckKey(item, "Value", out valueData)).Failed) return result;
|
||||
|
||||
object keyInstance = null, valueInstance = null;
|
||||
if ((result += Serializer.TryDeserialize(keyData, keyStorageType, ref keyInstance)).Failed) return result;
|
||||
if ((result += Serializer.TryDeserialize(valueData, valueStorageType, ref valueInstance)).Failed) return result;
|
||||
|
||||
AddItemToDictionary(instance, keyInstance, valueInstance);
|
||||
}
|
||||
}
|
||||
else if (data.IsDictionary) {
|
||||
foreach (var entry in data.AsDictionary) {
|
||||
if (fsSerializer.IsReservedKeyword(entry.Key)) continue;
|
||||
|
||||
fsData keyData = new fsData(entry.Key), valueData = entry.Value;
|
||||
object keyInstance = null, valueInstance = null;
|
||||
|
||||
if ((result += Serializer.TryDeserialize(keyData, keyStorageType, ref keyInstance)).Failed) return result;
|
||||
if ((result += Serializer.TryDeserialize(valueData, valueStorageType, ref valueInstance)).Failed) return result;
|
||||
|
||||
AddItemToDictionary(instance, keyInstance, valueInstance);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FailExpectedType(data, fsDataType.Array, fsDataType.Object);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance_, out fsData serialized, Type storageType) {
|
||||
serialized = fsData.Null;
|
||||
|
||||
var result = fsResult.Success;
|
||||
|
||||
var instance = (IDictionary)instance_;
|
||||
|
||||
Type keyStorageType, valueStorageType;
|
||||
GetKeyValueTypes(instance.GetType(), out keyStorageType, out valueStorageType);
|
||||
|
||||
// No other way to iterate dictionaries and still have access to the key/value info
|
||||
IDictionaryEnumerator enumerator = instance.GetEnumerator();
|
||||
|
||||
bool allStringKeys = true;
|
||||
var serializedKeys = new List<fsData>(instance.Count);
|
||||
var serializedValues = new List<fsData>(instance.Count);
|
||||
while (enumerator.MoveNext()) {
|
||||
fsData keyData, valueData;
|
||||
if ((result += Serializer.TrySerialize(keyStorageType, enumerator.Key, out keyData)).Failed) return result;
|
||||
if ((result += Serializer.TrySerialize(valueStorageType, enumerator.Value, out valueData)).Failed) return result;
|
||||
|
||||
serializedKeys.Add(keyData);
|
||||
serializedValues.Add(valueData);
|
||||
|
||||
allStringKeys &= keyData.IsString;
|
||||
}
|
||||
|
||||
if (allStringKeys) {
|
||||
serialized = fsData.CreateDictionary();
|
||||
var serializedDictionary = serialized.AsDictionary;
|
||||
|
||||
for (int i = 0; i < serializedKeys.Count; ++i) {
|
||||
fsData key = serializedKeys[i];
|
||||
fsData value = serializedValues[i];
|
||||
serializedDictionary[key.AsString] = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
serialized = fsData.CreateList(serializedKeys.Count);
|
||||
var serializedList = serialized.AsList;
|
||||
|
||||
for (int i = 0; i < serializedKeys.Count; ++i) {
|
||||
fsData key = serializedKeys[i];
|
||||
fsData value = serializedValues[i];
|
||||
|
||||
var container = new Dictionary<string, fsData>();
|
||||
container["Key"] = key;
|
||||
container["Value"] = value;
|
||||
serializedList.Add(new fsData(container));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private fsResult AddItemToDictionary(IDictionary dictionary, object key, object value) {
|
||||
// Because we're operating through the IDictionary interface by default (and not the
|
||||
// generic one), we normally send items through IDictionary.Add(object, object). This
|
||||
// works fine in the general case, except that the add method verifies that it's
|
||||
// parameter types are proper types. However, mono is buggy and these type checks do
|
||||
// not consider null a subtype of the parameter types, and exceptions get thrown. So,
|
||||
// we have to special case adding null items via the generic functions (which do not
|
||||
// do the null check), which is slow and messy.
|
||||
//
|
||||
// An example of a collection that fails deserialization without this method is
|
||||
// `new SortedList<int, string> { { 0, null } }`. (SortedDictionary is fine because
|
||||
// it properly handles null values).
|
||||
if (key == null || value == null) {
|
||||
// Life would be much easier if we had MakeGenericType available, but we don't. So
|
||||
// we're going to find the correct generic KeyValuePair type via a bit of trickery.
|
||||
// All dictionaries extend ICollection<KeyValuePair<TKey, TValue>>, so we just
|
||||
// fetch the ICollection<> type with the proper generic arguments, and then we take
|
||||
// the KeyValuePair<> generic argument, and whola! we have our proper generic type.
|
||||
|
||||
var collectionType = fsReflectionUtility.GetInterface(dictionary.GetType(), typeof(ICollection<>));
|
||||
if (collectionType == null) {
|
||||
return fsResult.Warn(dictionary.GetType() + " does not extend ICollection");
|
||||
}
|
||||
|
||||
var keyValuePairType = collectionType.GetGenericArguments()[0];
|
||||
object keyValueInstance = Activator.CreateInstance(keyValuePairType, key, value);
|
||||
MethodInfo add = collectionType.GetFlattenedMethod("Add");
|
||||
add.Invoke(dictionary, new object[] { keyValueInstance });
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
// We use the inline set methods instead of dictionary.Add; dictionary.Add will throw an exception
|
||||
// if the key already exists.
|
||||
dictionary[key] = value;
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
private static void GetKeyValueTypes(Type dictionaryType, out Type keyStorageType, out Type valueStorageType) {
|
||||
// All dictionaries extend IDictionary<TKey, TValue>, so we just fetch the generic arguments from it
|
||||
var interfaceType = fsReflectionUtility.GetInterface(dictionaryType, typeof(IDictionary<,>));
|
||||
if (interfaceType != null) {
|
||||
var genericArgs = interfaceType.GetGenericArguments();
|
||||
keyStorageType = genericArgs[0];
|
||||
valueStorageType = genericArgs[1];
|
||||
}
|
||||
|
||||
else {
|
||||
// Fetching IDictionary<,> failed... we have to encode full type information :(
|
||||
keyStorageType = typeof(object);
|
||||
valueStorageType = typeof(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c1fd84fc9c6dda4088367b5859c04a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,105 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Serializes and deserializes enums by their current name.
|
||||
/// </summary>
|
||||
public class fsEnumConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return type.Resolve().IsEnum;
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
// In .NET compact, Enum.ToObject(Type, Object) is defined but the overloads like
|
||||
// Enum.ToObject(Type, int) are not -- so we get around this by boxing the value.
|
||||
return Enum.ToObject(storageType, (object)0);
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
if (Serializer.Config.SerializeEnumsAsInteger) {
|
||||
serialized = new fsData(Convert.ToInt64(instance));
|
||||
}
|
||||
else if (fsPortableReflection.GetAttribute<FlagsAttribute>(storageType) != null) {
|
||||
long instanceValue = Convert.ToInt64(instance);
|
||||
var result = new StringBuilder();
|
||||
|
||||
bool first = true;
|
||||
foreach (var value in Enum.GetValues(storageType)) {
|
||||
long integralValue = Convert.ToInt64(value);
|
||||
bool isSet = (instanceValue & integralValue) != 0;
|
||||
|
||||
if (isSet) {
|
||||
if (first == false) result.Append(",");
|
||||
first = false;
|
||||
result.Append(value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
serialized = new fsData(result.ToString());
|
||||
}
|
||||
else {
|
||||
serialized = new fsData(Enum.GetName(storageType, instance));
|
||||
}
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
if (data.IsString) {
|
||||
string[] enumValues = data.AsString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
long instanceValue = 0;
|
||||
for (int i = 0; i < enumValues.Length; ++i) {
|
||||
string enumValue = enumValues[i];
|
||||
|
||||
// Verify that the enum name exists; Enum.TryParse is only available in .NET 4.0
|
||||
// and above :(.
|
||||
if (ArrayContains(Enum.GetNames(storageType), enumValue) == false) {
|
||||
return fsResult.Fail("Cannot find enum name " + enumValue + " on type " + storageType);
|
||||
}
|
||||
|
||||
long flagValue = (long)Convert.ChangeType(Enum.Parse(storageType, enumValue), typeof(long));
|
||||
instanceValue |= flagValue;
|
||||
}
|
||||
|
||||
instance = Enum.ToObject(storageType, (object)instanceValue);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
else if (data.IsInt64) {
|
||||
int enumValue = (int)data.AsInt64;
|
||||
|
||||
// In .NET compact, Enum.ToObject(Type, Object) is defined but the overloads like
|
||||
// Enum.ToObject(Type, int) are not -- so we get around this by boxing the value.
|
||||
instance = Enum.ToObject(storageType, (object)enumValue);
|
||||
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
return fsResult.Fail("EnumConverter encountered an unknown JSON data type");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given value is contained within the specified array.
|
||||
/// </summary>
|
||||
private static bool ArrayContains<T>(T[] values, T value) {
|
||||
// note: We don't use LINQ because this function will *not* allocate
|
||||
for (int i = 0; i < values.Length; ++i) {
|
||||
if (EqualityComparer<T>.Default.Equals(values[i], value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c560df084b66b254ab5e9bdfc847c7bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,86 +0,0 @@
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 89892b3279cd6e249838f8b44cc0f838
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,39 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Serializes and deserializes guids.
|
||||
/// </summary>
|
||||
public class fsGuidConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return type == typeof(Guid);
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
var guid = (Guid)instance;
|
||||
serialized = new fsData(guid.ToString());
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
if (data.IsString) {
|
||||
instance = new Guid(data.AsString);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
return fsResult.Fail("fsGuidConverter encountered an unknown JSON data type");
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new Guid();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 09373a87560925948a4a8343e4edb9ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,145 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Provides serialization support for anything which extends from `IEnumerable` and has an `Add` method.
|
||||
/// </summary>
|
||||
public class fsIEnumerableConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type) == false) return false;
|
||||
return GetAddMethod(type) != null;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance_, out fsData serialized, Type storageType) {
|
||||
var instance = (IEnumerable)instance_;
|
||||
var result = fsResult.Success;
|
||||
|
||||
Type elementType = GetElementType(storageType);
|
||||
|
||||
serialized = fsData.CreateList(HintSize(instance));
|
||||
var serializedList = serialized.AsList;
|
||||
|
||||
foreach (object item in instance) {
|
||||
fsData itemData;
|
||||
|
||||
// note: We don't fail the entire deserialization even if the item failed
|
||||
var itemResult = Serializer.TrySerialize(elementType, item, out itemData);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) continue;
|
||||
|
||||
serializedList.Add(itemData);
|
||||
}
|
||||
|
||||
// Stacks iterate from back to front, which means when we deserialize we will deserialize
|
||||
// the items in the wrong order, so the stack will get reversed.
|
||||
if (IsStack(instance.GetType())) {
|
||||
serializedList.Reverse();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool IsStack(Type type) {
|
||||
return type.Resolve().IsGenericType &&
|
||||
type.Resolve().GetGenericTypeDefinition() == typeof(Stack<>);
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance_, Type storageType) {
|
||||
var instance = (IEnumerable)instance_;
|
||||
var result = fsResult.Success;
|
||||
|
||||
if ((result += CheckType(data, fsDataType.Array)).Failed) return result;
|
||||
|
||||
// For general strategy, instance may already have items in it. We will try to deserialize into
|
||||
// the existing element.
|
||||
var elementStorageType = GetElementType(storageType);
|
||||
var addMethod = GetAddMethod(storageType);
|
||||
var getMethod = storageType.GetFlattenedMethod("get_Item");
|
||||
var setMethod = storageType.GetFlattenedMethod("set_Item");
|
||||
if (setMethod == null) TryClear(storageType, instance);
|
||||
var existingSize = TryGetExistingSize(storageType, instance);
|
||||
|
||||
var serializedList = data.AsList;
|
||||
for (int i = 0; i < serializedList.Count; ++i) {
|
||||
var itemData = serializedList[i];
|
||||
object itemInstance = null;
|
||||
if (getMethod != null && i < existingSize) {
|
||||
itemInstance = getMethod.Invoke(instance, new object[] { i });
|
||||
}
|
||||
|
||||
// note: We don't fail the entire deserialization even if the item failed
|
||||
var itemResult = Serializer.TryDeserialize(itemData, elementStorageType, ref itemInstance);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) continue;
|
||||
|
||||
if (setMethod != null && i < existingSize) {
|
||||
setMethod.Invoke(instance, new object[] { i, itemInstance });
|
||||
}
|
||||
else {
|
||||
addMethod.Invoke(instance, new object[] { itemInstance });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int HintSize(IEnumerable collection) {
|
||||
if (collection is ICollection) {
|
||||
return ((ICollection)collection).Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the element type for objects inside of the collection.
|
||||
/// </summary>
|
||||
private static Type GetElementType(Type objectType) {
|
||||
if (objectType.HasElementType) return objectType.GetElementType();
|
||||
|
||||
Type enumerableList = fsReflectionUtility.GetInterface(objectType, typeof(IEnumerable<>));
|
||||
if (enumerableList != null) return enumerableList.GetGenericArguments()[0];
|
||||
|
||||
return typeof(object);
|
||||
}
|
||||
|
||||
private static void TryClear(Type type, object instance) {
|
||||
var clear = type.GetFlattenedMethod("Clear");
|
||||
if (clear != null) {
|
||||
clear.Invoke(instance, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static int TryGetExistingSize(Type type, object instance) {
|
||||
var count = type.GetFlattenedProperty("Count");
|
||||
if (count != null) {
|
||||
return (int)count.GetGetMethod().Invoke(instance, null);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static MethodInfo GetAddMethod(Type type) {
|
||||
// There is a really good chance the type will extend ICollection{}, which will contain
|
||||
// the add method we want. Just doing type.GetFlattenedMethod() may return the incorrect one --
|
||||
// for example, with dictionaries, it'll return Add(TKey, TValue), and we want
|
||||
// Add(KeyValuePair<TKey, TValue>).
|
||||
Type collectionInterface = fsReflectionUtility.GetInterface(type, typeof(ICollection<>));
|
||||
if (collectionInterface != null) {
|
||||
MethodInfo add = collectionInterface.GetDeclaredMethod("Add");
|
||||
if (add != null) return add;
|
||||
}
|
||||
|
||||
// Otherwise try and look up a general Add method.
|
||||
return
|
||||
type.GetFlattenedMethod("Add") ??
|
||||
type.GetFlattenedMethod("Push") ??
|
||||
type.GetFlattenedMethod("Enqueue");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4a7fdd4014dc894458c54513809a2998
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,62 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsKeyValuePairConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return
|
||||
type.Resolve().IsGenericType &&
|
||||
type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>);
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
fsData keyData, valueData;
|
||||
if ((result += CheckKey(data, "Key", out keyData)).Failed) return result;
|
||||
if ((result += CheckKey(data, "Value", out valueData)).Failed) return result;
|
||||
|
||||
var genericArguments = storageType.GetGenericArguments();
|
||||
Type keyType = genericArguments[0], valueType = genericArguments[1];
|
||||
|
||||
object keyObject = null, valueObject = null;
|
||||
result.AddMessages(Serializer.TryDeserialize(keyData, keyType, ref keyObject));
|
||||
result.AddMessages(Serializer.TryDeserialize(valueData, valueType, ref valueObject));
|
||||
|
||||
instance = Activator.CreateInstance(storageType, keyObject, valueObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
PropertyInfo keyProperty = storageType.GetDeclaredProperty("Key");
|
||||
PropertyInfo valueProperty = storageType.GetDeclaredProperty("Value");
|
||||
|
||||
object keyObject = keyProperty.GetValue(instance, null);
|
||||
object valueObject = valueProperty.GetValue(instance, null);
|
||||
|
||||
var genericArguments = storageType.GetGenericArguments();
|
||||
Type keyType = genericArguments[0], valueType = genericArguments[1];
|
||||
|
||||
var result = fsResult.Success;
|
||||
|
||||
fsData keyData, valueData;
|
||||
result.AddMessages(Serializer.TrySerialize(keyType, keyObject, out keyData));
|
||||
result.AddMessages(Serializer.TrySerialize(valueType, valueObject, out valueData));
|
||||
|
||||
serialized = fsData.CreateDictionary();
|
||||
if (keyData != null) serialized.AsDictionary["Key"] = keyData;
|
||||
if (valueData != null) serialized.AsDictionary["Value"] = valueData;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a3857f6e037d454194843e278772b9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,29 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// The reflected converter will properly serialize nullable types. However, we do it here
|
||||
/// instead as we can emit less serialization data.
|
||||
/// </summary>
|
||||
public class fsNullableConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return
|
||||
type.Resolve().IsGenericType &&
|
||||
type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
// null is automatically serialized
|
||||
return Serializer.TrySerialize(Nullable.GetUnderlyingType(storageType), instance, out serialized);
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
// null is automatically deserialized
|
||||
return Serializer.TryDeserialize(data, Nullable.GetUnderlyingType(storageType), ref instance);
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return storageType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 71d2abb9701478740b1fbb8720a63a24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,125 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsPrimitiveConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return
|
||||
type.Resolve().IsPrimitive ||
|
||||
type == typeof(string) ||
|
||||
type == typeof(decimal);
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool UseBool(Type type) {
|
||||
return type == typeof(bool);
|
||||
}
|
||||
|
||||
private static bool UseInt64(Type type) {
|
||||
return type == typeof(sbyte) || type == typeof(byte) ||
|
||||
type == typeof(Int16) || type == typeof(UInt16) ||
|
||||
type == typeof(Int32) || type == typeof(UInt32) ||
|
||||
type == typeof(Int64) || type == typeof(UInt64);
|
||||
}
|
||||
|
||||
private static bool UseDouble(Type type) {
|
||||
return type == typeof(float) ||
|
||||
type == typeof(double) ||
|
||||
type == typeof(decimal);
|
||||
}
|
||||
|
||||
private static bool UseString(Type type) {
|
||||
return type == typeof(string) ||
|
||||
type == typeof(char);
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
var instanceType = instance.GetType();
|
||||
|
||||
if (Serializer.Config.Serialize64BitIntegerAsString && (instanceType == typeof(Int64) || instanceType == typeof(UInt64))) {
|
||||
serialized = new fsData((string)Convert.ChangeType(instance, typeof(string)));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (UseBool(instanceType)) {
|
||||
serialized = new fsData((bool)instance);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (UseInt64(instanceType)) {
|
||||
serialized = new fsData((Int64)Convert.ChangeType(instance, typeof(Int64)));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (UseDouble(instanceType)) {
|
||||
// Casting from float to double introduces floating point jitter, ie, 0.1 becomes 0.100000001490116.
|
||||
// Casting to decimal as an intermediate step removes the jitter. Not sure why.
|
||||
if (instance.GetType() == typeof(float) &&
|
||||
// Decimal can't store float.MinValue/float.MaxValue/float.PositiveInfinity/float.NegativeInfinity/float.NaN - an exception gets thrown in that scenario.
|
||||
(float)instance != float.MinValue &&
|
||||
(float)instance != float.MaxValue &&
|
||||
!float.IsInfinity((float)instance) &&
|
||||
!float.IsNaN((float)instance)
|
||||
) {
|
||||
serialized = new fsData((double)(decimal)(float)instance);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
serialized = new fsData((double)Convert.ChangeType(instance, typeof(double)));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (UseString(instanceType)) {
|
||||
serialized = new fsData((string)Convert.ChangeType(instance, typeof(string)));
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
serialized = null;
|
||||
return fsResult.Fail("Unhandled primitive type " + instance.GetType());
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData storage, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
if (UseBool(storageType)) {
|
||||
if ((result += CheckType(storage, fsDataType.Boolean)).Succeeded) {
|
||||
instance = storage.AsBool;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (UseDouble(storageType) || UseInt64(storageType)) {
|
||||
if (storage.IsDouble) {
|
||||
instance = Convert.ChangeType(storage.AsDouble, storageType);
|
||||
}
|
||||
else if (storage.IsInt64) {
|
||||
instance = Convert.ChangeType(storage.AsInt64, storageType);
|
||||
}
|
||||
else if (Serializer.Config.Serialize64BitIntegerAsString && storage.IsString &&
|
||||
(storageType == typeof(Int64) || storageType == typeof(UInt64))) {
|
||||
instance = Convert.ChangeType(storage.AsString, storageType);
|
||||
}
|
||||
else {
|
||||
return fsResult.Fail(GetType().Name + " expected number but got " + storage.Type + " in " + storage);
|
||||
}
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
if (UseString(storageType)) {
|
||||
if ((result += CheckType(storage, fsDataType.String)).Succeeded) {
|
||||
instance = storage.AsString;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return fsResult.Fail(GetType().Name + ": Bad data; expected bool, number, string, but got " + storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 790de8a8a4ec95444ac95d5a812d69b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,93 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WSA
|
||||
// For System.Reflection.TypeExtensions
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsReflectedConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
if (type.Resolve().IsArray ||
|
||||
typeof(ICollection).IsAssignableFrom(type)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
serialized = fsData.CreateDictionary();
|
||||
var result = fsResult.Success;
|
||||
|
||||
fsMetaType metaType = fsMetaType.Get(Serializer.Config, instance.GetType());
|
||||
metaType.EmitAotData();
|
||||
|
||||
for (int i = 0; i < metaType.Properties.Length; ++i) {
|
||||
fsMetaProperty property = metaType.Properties[i];
|
||||
if (property.CanRead == false) continue;
|
||||
|
||||
fsData serializedData;
|
||||
|
||||
var itemResult = Serializer.TrySerialize(property.StorageType, property.OverrideConverterType,
|
||||
property.Read(instance), out serializedData);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
serialized.AsDictionary[property.JsonName] = serializedData;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
// Verify that we actually have an Object
|
||||
if ((result += CheckType(data, fsDataType.Object)).Failed) {
|
||||
return result;
|
||||
}
|
||||
|
||||
fsMetaType metaType = fsMetaType.Get(Serializer.Config, storageType);
|
||||
metaType.EmitAotData();
|
||||
|
||||
for (int i = 0; i < metaType.Properties.Length; ++i) {
|
||||
fsMetaProperty property = metaType.Properties[i];
|
||||
if (property.CanWrite == false) continue;
|
||||
|
||||
fsData propertyData;
|
||||
if (data.AsDictionary.TryGetValue(property.JsonName, out propertyData)) {
|
||||
object deserializedValue = null;
|
||||
|
||||
// We have to read in the existing value, since we need to support partial
|
||||
// deserialization. However, this is bad for perf.
|
||||
// TODO: Find a way to avoid this call when we are not doing a partial deserialization
|
||||
// Maybe through a new property, ie, Serializer.IsPartialSerialization, which just
|
||||
// gets set when starting a new serialization? We cannot pipe the information
|
||||
// through CreateInstance unfortunately.
|
||||
if (property.CanRead) {
|
||||
deserializedValue = property.Read(instance);
|
||||
}
|
||||
|
||||
var itemResult = Serializer.TryDeserialize(propertyData, property.StorageType,
|
||||
property.OverrideConverterType, ref deserializedValue);
|
||||
result.AddMessages(itemResult);
|
||||
if (itemResult.Failed) continue;
|
||||
|
||||
property.Write(instance, deserializedValue);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
fsMetaType metaType = fsMetaType.Get(Serializer.Config, storageType);
|
||||
return metaType.CreateInstance();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a23ca5511c2d3cc4692dfc7f11d9ed67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,44 +0,0 @@
|
|||
using System;
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WSA
|
||||
// For System.Reflection.TypeExtensions
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsTypeConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return typeof(Type).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
var type = (Type)instance;
|
||||
serialized = new fsData(type.FullName);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
if (data.IsString == false) {
|
||||
return fsResult.Fail("Type converter requires a string");
|
||||
}
|
||||
|
||||
instance = fsTypeCache.GetType(data.AsString);
|
||||
if (instance == null) {
|
||||
return fsResult.Fail("Unable to find type " + data.AsString);
|
||||
}
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return storageType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aba11236805ed6b4a9f9616bc70a02d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,65 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Serializes and deserializes WeakReferences.
|
||||
/// </summary>
|
||||
public class fsWeakReferenceConverter : fsConverter {
|
||||
public override bool CanProcess(Type type) {
|
||||
return type == typeof(WeakReference);
|
||||
}
|
||||
|
||||
public override bool RequestCycleSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool RequestInheritanceSupport(Type storageType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
var weakRef = (WeakReference)instance;
|
||||
|
||||
var result = fsResult.Success;
|
||||
serialized = fsData.CreateDictionary();
|
||||
|
||||
if (weakRef.IsAlive) {
|
||||
fsData data;
|
||||
if ((result += Serializer.TrySerialize(weakRef.Target, out data)).Failed) {
|
||||
return result;
|
||||
}
|
||||
|
||||
serialized.AsDictionary["Target"] = data;
|
||||
serialized.AsDictionary["TrackResurrection"] = new fsData(weakRef.TrackResurrection);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
|
||||
if ((result += CheckType(data, fsDataType.Object)).Failed) return result;
|
||||
|
||||
if (data.AsDictionary.ContainsKey("Target")) {
|
||||
var targetData = data.AsDictionary["Target"];
|
||||
object targetInstance = null;
|
||||
|
||||
if ((result += Serializer.TryDeserialize(targetData, typeof(object), ref targetInstance)).Failed) return result;
|
||||
|
||||
bool trackResurrection = false;
|
||||
if (data.AsDictionary.ContainsKey("TrackResurrection") && data.AsDictionary["TrackResurrection"].IsBool) {
|
||||
trackResurrection = data.AsDictionary["TrackResurrection"].AsBool;
|
||||
}
|
||||
|
||||
instance = new WeakReference(targetInstance, trackResurrection);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object CreateInstance(fsData data, Type storageType) {
|
||||
return new WeakReference(null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ebce9d110c1f6744f9a17efb7097f566
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3773692a867995d489411837599e3761
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,90 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsCyclicReferenceManager {
|
||||
// We use the default ReferenceEquals when comparing two objects because
|
||||
// custom objects may override equals methods. These overriden equals may
|
||||
// treat equals differently; we want to serialize/deserialize the object
|
||||
// graph *identically* to how it currently exists.
|
||||
class ObjectReferenceEqualityComparator : IEqualityComparer<object> {
|
||||
bool IEqualityComparer<object>.Equals(object x, object y) {
|
||||
return ReferenceEquals(x, y);
|
||||
}
|
||||
|
||||
int IEqualityComparer<object>.GetHashCode(object obj) {
|
||||
return RuntimeHelpers.GetHashCode(obj);
|
||||
}
|
||||
|
||||
public static readonly IEqualityComparer<object> Instance = new ObjectReferenceEqualityComparator();
|
||||
}
|
||||
|
||||
private Dictionary<object, int> _objectIds = new Dictionary<object, int>(ObjectReferenceEqualityComparator.Instance);
|
||||
private int _nextId;
|
||||
|
||||
private Dictionary<int, object> _marked = new Dictionary<int, object>();
|
||||
private int _depth;
|
||||
|
||||
public void Enter() {
|
||||
_depth++;
|
||||
}
|
||||
|
||||
public bool Exit() {
|
||||
_depth--;
|
||||
|
||||
if (_depth == 0) {
|
||||
_objectIds = new Dictionary<object, int>(ObjectReferenceEqualityComparator.Instance);
|
||||
_nextId = 0;
|
||||
_marked = new Dictionary<int, object>();
|
||||
}
|
||||
|
||||
if (_depth < 0) {
|
||||
_depth = 0;
|
||||
throw new InvalidOperationException("Internal Error - Mismatched Enter/Exit");
|
||||
}
|
||||
|
||||
return _depth == 0;
|
||||
}
|
||||
|
||||
public object GetReferenceObject(int id) {
|
||||
if (_marked.ContainsKey(id) == false) {
|
||||
throw new InvalidOperationException("Internal Deserialization Error - Object " +
|
||||
"definition has not been encountered for object with id=" + id +
|
||||
"; have you reordered or modified the serialized data? If this is an issue " +
|
||||
"with an unmodified Full Serializer implementation and unmodified serialization " +
|
||||
"data, please report an issue with an included test case.");
|
||||
}
|
||||
|
||||
return _marked[id];
|
||||
}
|
||||
|
||||
public void AddReferenceWithId(int id, object reference) {
|
||||
_marked[id] = reference;
|
||||
}
|
||||
|
||||
public int GetReferenceId(object item) {
|
||||
int id;
|
||||
if (_objectIds.TryGetValue(item, out id) == false) {
|
||||
id = _nextId++;
|
||||
_objectIds[item] = id;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public bool IsReference(object item) {
|
||||
return _marked.ContainsKey(GetReferenceId(item));
|
||||
}
|
||||
|
||||
public void MarkSerialized(object item) {
|
||||
int referenceId = GetReferenceId(item);
|
||||
|
||||
if (_marked.ContainsKey(referenceId)) {
|
||||
throw new InvalidOperationException("Internal Error - " + item +
|
||||
" has already been marked as serialized");
|
||||
}
|
||||
|
||||
_marked[referenceId] = item;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c34d55229bfe53d47a9ea7cf23687186
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,37 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Simple option type. This is akin to nullable types.
|
||||
/// </summary>
|
||||
public struct fsOption<T> {
|
||||
private bool _hasValue;
|
||||
private T _value;
|
||||
|
||||
public bool HasValue {
|
||||
get { return _hasValue; }
|
||||
}
|
||||
public bool IsEmpty {
|
||||
get { return _hasValue == false; }
|
||||
}
|
||||
public T Value {
|
||||
get {
|
||||
if (IsEmpty) throw new InvalidOperationException("fsOption is empty");
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
public fsOption(T value) {
|
||||
_hasValue = true;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public static fsOption<T> Empty;
|
||||
}
|
||||
|
||||
public static class fsOption {
|
||||
public static fsOption<T> Just<T>(T value) {
|
||||
return new fsOption<T>(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ec455db28b0ad7e4095c55696c9c630f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,400 +0,0 @@
|
|||
#if !UNITY_EDITOR && UNITY_METRO && !ENABLE_IL2CPP
|
||||
#define USE_TYPEINFO
|
||||
#if !UNITY_WINRT_10_0
|
||||
#define USE_TYPEINFO_EXTENSIONS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
#if USE_TYPEINFO
|
||||
namespace System {
|
||||
public static class AssemblyExtensions {
|
||||
#if USE_TYPEINFO_EXTENSIONS
|
||||
public static Type[] GetTypes(this Assembly assembly) {
|
||||
TypeInfo[] infos = assembly.DefinedTypes.ToArray();
|
||||
Type[] types = new Type[infos.Length];
|
||||
for (int i = 0; i < infos.Length; ++i) {
|
||||
types[i] = infos[i].AsType();
|
||||
}
|
||||
return types;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static Type GetType(this Assembly assembly, string name, bool throwOnError) {
|
||||
var types = assembly.GetTypes();
|
||||
for (int i = 0; i < types.Length; ++i) {
|
||||
if (types[i].Name == name) {
|
||||
return types[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnError) throw new Exception("Type " + name + " was not found");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// This wraps reflection types so that it is portable across different Unity runtimes.
|
||||
/// </summary>
|
||||
public static class fsPortableReflection {
|
||||
public static Type[] EmptyTypes = { };
|
||||
|
||||
#region Attribute Queries
|
||||
#if USE_TYPEINFO
|
||||
public static TAttribute GetAttribute<TAttribute>(Type type)
|
||||
where TAttribute : Attribute {
|
||||
|
||||
return GetAttribute<TAttribute>(type.GetTypeInfo());
|
||||
}
|
||||
|
||||
public static Attribute GetAttribute(Type type, Type attributeType) {
|
||||
return GetAttribute(type.GetTypeInfo(), attributeType, /*shouldCache:*/false);
|
||||
}
|
||||
|
||||
public static bool HasAttribute(Type type, Type attributeType) {
|
||||
return GetAttribute(type, attributeType) != null;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given attribute is defined on the given element.
|
||||
/// </summary>
|
||||
public static bool HasAttribute<TAttribute>(MemberInfo element) {
|
||||
return HasAttribute(element, typeof(TAttribute));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given attribute is defined on the given element.
|
||||
/// </summary>
|
||||
public static bool HasAttribute<TAttribute>(MemberInfo element, bool shouldCache) {
|
||||
return HasAttribute(element, typeof(TAttribute), shouldCache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given attribute is defined on the given element.
|
||||
/// </summary>
|
||||
public static bool HasAttribute(MemberInfo element, Type attributeType) {
|
||||
return HasAttribute(element, attributeType, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given attribute is defined on the given element.
|
||||
/// </summary>
|
||||
public static bool HasAttribute(MemberInfo element, Type attributeType, bool shouldCache) {
|
||||
return element.IsDefined(attributeType, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the given attribute from the given MemberInfo. This method applies caching
|
||||
/// and is allocation free (after caching has been performed).
|
||||
/// </summary>
|
||||
/// <param name="element">The MemberInfo the get the attribute from.</param>
|
||||
/// <param name="attributeType">The type of attribute to fetch.</param>
|
||||
/// <returns>The attribute or null.</returns>
|
||||
public static Attribute GetAttribute(MemberInfo element, Type attributeType, bool shouldCache) {
|
||||
var query = new AttributeQuery {
|
||||
MemberInfo = element,
|
||||
AttributeType = attributeType
|
||||
};
|
||||
|
||||
Attribute attribute;
|
||||
if (_cachedAttributeQueries.TryGetValue(query, out attribute) == false) {
|
||||
var attributes = element.GetCustomAttributes(attributeType, /*inherit:*/ true);
|
||||
if (attributes.Length > 0)
|
||||
attribute = (Attribute)attributes[0];
|
||||
if (shouldCache)
|
||||
_cachedAttributeQueries[query] = attribute;
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the given attribute from the given MemberInfo.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">The type of attribute to fetch.</typeparam>
|
||||
/// <param name="element">The MemberInfo to get the attribute from.</param>
|
||||
/// <param name="shouldCache">Should this computation be cached? If this is the only time it will ever be done, don't bother caching.</param>
|
||||
/// <returns>The attribute or null.</returns>
|
||||
public static TAttribute GetAttribute<TAttribute>(MemberInfo element, bool shouldCache)
|
||||
where TAttribute : Attribute {
|
||||
|
||||
return (TAttribute)GetAttribute(element, typeof(TAttribute), shouldCache);
|
||||
}
|
||||
public static TAttribute GetAttribute<TAttribute>(MemberInfo element)
|
||||
where TAttribute : Attribute {
|
||||
return GetAttribute<TAttribute>(element, /*shouldCache:*/true);
|
||||
}
|
||||
private struct AttributeQuery {
|
||||
public MemberInfo MemberInfo;
|
||||
public Type AttributeType;
|
||||
}
|
||||
private static IDictionary<AttributeQuery, Attribute> _cachedAttributeQueries =
|
||||
new Dictionary<AttributeQuery, Attribute>(new AttributeQueryComparator());
|
||||
private class AttributeQueryComparator : IEqualityComparer<AttributeQuery> {
|
||||
public bool Equals(AttributeQuery x, AttributeQuery y) {
|
||||
return
|
||||
x.MemberInfo == y.MemberInfo &&
|
||||
x.AttributeType == y.AttributeType;
|
||||
}
|
||||
|
||||
public int GetHashCode(AttributeQuery obj) {
|
||||
return
|
||||
obj.MemberInfo.GetHashCode() +
|
||||
(17 * obj.AttributeType.GetHashCode());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#if !USE_TYPEINFO
|
||||
private static BindingFlags DeclaredFlags =
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.DeclaredOnly;
|
||||
#endif
|
||||
|
||||
public static PropertyInfo GetDeclaredProperty(this Type type, string propertyName) {
|
||||
var props = GetDeclaredProperties(type);
|
||||
|
||||
for (int i = 0; i < props.Length; ++i) {
|
||||
if (props[i].Name == propertyName) {
|
||||
return props[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MethodInfo GetDeclaredMethod(this Type type, string methodName) {
|
||||
var methods = GetDeclaredMethods(type);
|
||||
|
||||
for (int i = 0; i < methods.Length; ++i) {
|
||||
if (methods[i].Name == methodName) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[] parameters) {
|
||||
var ctors = GetDeclaredConstructors(type);
|
||||
|
||||
for (int i = 0; i < ctors.Length; ++i) {
|
||||
var ctor = ctors[i];
|
||||
var ctorParams = ctor.GetParameters();
|
||||
|
||||
if (parameters.Length != ctorParams.Length) continue;
|
||||
|
||||
for (int j = 0; j < ctorParams.Length; ++j) {
|
||||
// require an exact match
|
||||
if (ctorParams[j].ParameterType != parameters[j]) continue;
|
||||
}
|
||||
|
||||
return ctor;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ConstructorInfo[] GetDeclaredConstructors(this Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo().DeclaredConstructors.ToArray();
|
||||
#else
|
||||
return type.GetConstructors(DeclaredFlags);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetFlattenedMember(this Type type, string memberName) {
|
||||
var result = new List<MemberInfo>();
|
||||
|
||||
while (type != null) {
|
||||
var members = GetDeclaredMembers(type);
|
||||
|
||||
for (int i = 0; i < members.Length; ++i) {
|
||||
if (members[i].Name == memberName) {
|
||||
result.Add(members[i]);
|
||||
}
|
||||
}
|
||||
|
||||
type = type.Resolve().BaseType;
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static MethodInfo GetFlattenedMethod(this Type type, string methodName) {
|
||||
while (type != null) {
|
||||
var methods = GetDeclaredMethods(type);
|
||||
|
||||
for (int i = 0; i < methods.Length; ++i) {
|
||||
if (methods[i].Name == methodName) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
|
||||
type = type.Resolve().BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodInfo> GetFlattenedMethods(this Type type, string methodName) {
|
||||
while (type != null) {
|
||||
var methods = GetDeclaredMethods(type);
|
||||
|
||||
for (int i = 0; i < methods.Length; ++i) {
|
||||
if (methods[i].Name == methodName) {
|
||||
yield return methods[i];
|
||||
}
|
||||
}
|
||||
|
||||
type = type.Resolve().BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static PropertyInfo GetFlattenedProperty(this Type type, string propertyName) {
|
||||
while (type != null) {
|
||||
var properties = GetDeclaredProperties(type);
|
||||
|
||||
for (int i = 0; i < properties.Length; ++i) {
|
||||
if (properties[i].Name == propertyName) {
|
||||
return properties[i];
|
||||
}
|
||||
}
|
||||
|
||||
type = type.Resolve().BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MemberInfo GetDeclaredMember(this Type type, string memberName) {
|
||||
var members = GetDeclaredMembers(type);
|
||||
|
||||
for (int i = 0; i < members.Length; ++i) {
|
||||
if (members[i].Name == memberName) {
|
||||
return members[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MethodInfo[] GetDeclaredMethods(this Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo().DeclaredMethods.ToArray();
|
||||
#else
|
||||
return type.GetMethods(DeclaredFlags);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static PropertyInfo[] GetDeclaredProperties(this Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo().DeclaredProperties.ToArray();
|
||||
#else
|
||||
return type.GetProperties(DeclaredFlags);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static FieldInfo[] GetDeclaredFields(this Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo().DeclaredFields.ToArray();
|
||||
#else
|
||||
return type.GetFields(DeclaredFlags);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetDeclaredMembers(this Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo().DeclaredMembers.ToArray();
|
||||
#else
|
||||
return type.GetMembers(DeclaredFlags);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static MemberInfo AsMemberInfo(Type type) {
|
||||
#if USE_TYPEINFO
|
||||
return type.GetTypeInfo();
|
||||
#else
|
||||
return type;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsType(MemberInfo member) {
|
||||
#if USE_TYPEINFO
|
||||
return member is TypeInfo;
|
||||
#else
|
||||
return member is Type;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Type AsType(MemberInfo member) {
|
||||
#if USE_TYPEINFO
|
||||
return ((TypeInfo)member).AsType();
|
||||
#else
|
||||
return (Type)member;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_TYPEINFO
|
||||
public static TypeInfo Resolve(this Type type) {
|
||||
return type.GetTypeInfo();
|
||||
}
|
||||
#else
|
||||
public static Type Resolve(this Type type) {
|
||||
return type;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#region Extensions
|
||||
|
||||
#if USE_TYPEINFO_EXTENSIONS
|
||||
public static bool IsAssignableFrom(this Type parent, Type child) {
|
||||
return parent.GetTypeInfo().IsAssignableFrom(child.GetTypeInfo());
|
||||
}
|
||||
|
||||
public static Type GetElementType(this Type type) {
|
||||
return type.GetTypeInfo().GetElementType();
|
||||
}
|
||||
|
||||
public static MethodInfo GetSetMethod(this PropertyInfo member, bool nonPublic = false) {
|
||||
// only public requested but the set method is not public
|
||||
if (nonPublic == false && member.SetMethod != null && member.SetMethod.IsPublic == false) return null;
|
||||
|
||||
return member.SetMethod;
|
||||
}
|
||||
|
||||
public static MethodInfo GetGetMethod(this PropertyInfo member, bool nonPublic = false) {
|
||||
// only public requested but the set method is not public
|
||||
if (nonPublic == false && member.GetMethod != null && member.GetMethod.IsPublic == false) return null;
|
||||
|
||||
return member.GetMethod;
|
||||
}
|
||||
|
||||
public static MethodInfo GetBaseDefinition(this MethodInfo method) {
|
||||
return method.GetRuntimeBaseDefinition();
|
||||
}
|
||||
|
||||
public static Type[] GetInterfaces(this Type type) {
|
||||
return type.GetTypeInfo().ImplementedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
public static Type[] GetGenericArguments(this Type type) {
|
||||
return type.GetTypeInfo().GenericTypeArguments.ToArray();
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 917955f7b7d77724d8abc90bd462de25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,78 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WSA
|
||||
// For System.Reflection.TypeExtensions
|
||||
using System.Reflection;
|
||||
// For Reflection Extensions in non-win10 builds.
|
||||
using FullSerializer.Internal;
|
||||
#endif
|
||||
|
||||
namespace FullSerializer {
|
||||
public static class fsTypeExtensions {
|
||||
/// <summary>
|
||||
/// Returns a pretty name for the type in the style of one that you'd see in C# without the namespace.
|
||||
/// </summary>
|
||||
public static string CSharpName(this Type type) {
|
||||
return CSharpName(type, /*includeNamespace:*/false);
|
||||
}
|
||||
|
||||
public static string CSharpName(this Type type, bool includeNamespace, bool ensureSafeDeclarationName) {
|
||||
var name = CSharpName(type, includeNamespace);
|
||||
if (ensureSafeDeclarationName) name = name.Replace('>', '_').Replace('<', '_').Replace('.', '_');
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a pretty name for the type in the style of one that you'd see in C#.
|
||||
/// </summary>
|
||||
/// <parparam name="includeNamespace">Should the name include namespaces?</parparam>
|
||||
public static string CSharpName(this Type type, bool includeNamespace) {
|
||||
// we special case some of the common type names
|
||||
if (type == typeof(void)) return "void";
|
||||
if (type == typeof(int)) return "int";
|
||||
if (type == typeof(float)) return "float";
|
||||
if (type == typeof(bool)) return "bool";
|
||||
if (type == typeof(double)) return "double";
|
||||
if (type == typeof(string)) return "string";
|
||||
|
||||
// Generic parameter, ie, T in Okay<T>
|
||||
// We special-case this logic otherwise we will recurse on the T
|
||||
if (type.IsGenericParameter) {
|
||||
return type.ToString();
|
||||
}
|
||||
|
||||
string name = "";
|
||||
|
||||
var genericArguments = (IEnumerable<Type>)type.GetGenericArguments();
|
||||
if (type.IsNested) {
|
||||
name += type.DeclaringType.CSharpName() + ".";
|
||||
|
||||
// The declaring type generic parameters are considered part of the nested types generic
|
||||
// parameters so we need to remove them, otherwise it will get included again.
|
||||
//
|
||||
// Say we have type `class Parent<T> { class Child {} }`
|
||||
// If we did not do the removal, then we would output Parent<T>.Child<T>, but we really want
|
||||
// to output Parent<T>.Child
|
||||
if (type.DeclaringType.GetGenericArguments().Length > 0) {
|
||||
genericArguments = genericArguments.Skip(type.DeclaringType.GetGenericArguments().Length);
|
||||
}
|
||||
}
|
||||
|
||||
if (genericArguments.Any() == false) {
|
||||
name += type.Name;
|
||||
}
|
||||
else {
|
||||
name += type.Name.Substring(0, type.Name.IndexOf('`'));
|
||||
name += "<" + String.Join(",", genericArguments.Select(t => CSharpName(t, includeNamespace)).ToArray()) + ">";
|
||||
}
|
||||
|
||||
if (includeNamespace && type.Namespace != null) {
|
||||
name = type.Namespace + "." + name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34f8987a390a2ee488a60e2bc91e9614
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,132 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public static class fsVersionManager {
|
||||
private static readonly Dictionary<Type, fsOption<fsVersionedType>> _cache = new Dictionary<Type, fsOption<fsVersionedType>>();
|
||||
|
||||
public static fsResult GetVersionImportPath(string currentVersion, fsVersionedType targetVersion, out List<fsVersionedType> path) {
|
||||
path = new List<fsVersionedType>();
|
||||
|
||||
if (GetVersionImportPathRecursive(path, currentVersion, targetVersion) == false) {
|
||||
return fsResult.Fail("There is no migration path from \"" + currentVersion + "\" to \"" + targetVersion.VersionString + "\"");
|
||||
}
|
||||
|
||||
path.Add(targetVersion);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
private static bool GetVersionImportPathRecursive(List<fsVersionedType> path, string currentVersion, fsVersionedType current) {
|
||||
for (int i = 0; i < current.Ancestors.Length; ++i) {
|
||||
fsVersionedType ancestor = current.Ancestors[i];
|
||||
|
||||
if (ancestor.VersionString == currentVersion ||
|
||||
GetVersionImportPathRecursive(path, currentVersion, ancestor)) {
|
||||
|
||||
path.Add(ancestor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static fsOption<fsVersionedType> GetVersionedType(Type type) {
|
||||
fsOption<fsVersionedType> optionalVersionedType;
|
||||
|
||||
if (_cache.TryGetValue(type, out optionalVersionedType) == false) {
|
||||
var attr = fsPortableReflection.GetAttribute<fsObjectAttribute>(type);
|
||||
|
||||
if (attr != null) {
|
||||
if (string.IsNullOrEmpty(attr.VersionString) == false || attr.PreviousModels != null) {
|
||||
// Version string must be provided
|
||||
if (attr.PreviousModels != null && string.IsNullOrEmpty(attr.VersionString)) {
|
||||
throw new Exception("fsObject attribute on " + type + " contains a PreviousModels specifier - it must also include a VersionString modifier");
|
||||
}
|
||||
|
||||
// Map the ancestor types into versioned types
|
||||
fsVersionedType[] ancestors = new fsVersionedType[attr.PreviousModels != null ? attr.PreviousModels.Length : 0];
|
||||
for (int i = 0; i < ancestors.Length; ++i) {
|
||||
fsOption<fsVersionedType> ancestorType = GetVersionedType(attr.PreviousModels[i]);
|
||||
if (ancestorType.IsEmpty) {
|
||||
throw new Exception("Unable to create versioned type for ancestor " + ancestorType + "; please add an [fsObject(VersionString=\"...\")] attribute");
|
||||
}
|
||||
ancestors[i] = ancestorType.Value;
|
||||
}
|
||||
|
||||
// construct the actual versioned type instance
|
||||
fsVersionedType versionedType = new fsVersionedType {
|
||||
Ancestors = ancestors,
|
||||
VersionString = attr.VersionString,
|
||||
ModelType = type
|
||||
};
|
||||
|
||||
// finally, verify that the versioned type passes some sanity checks
|
||||
VerifyUniqueVersionStrings(versionedType);
|
||||
VerifyConstructors(versionedType);
|
||||
|
||||
optionalVersionedType = fsOption.Just(versionedType);
|
||||
}
|
||||
}
|
||||
|
||||
_cache[type] = optionalVersionedType;
|
||||
}
|
||||
|
||||
return optionalVersionedType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the given type has constructors to migrate from all ancestor types.
|
||||
/// </summary>
|
||||
private static void VerifyConstructors(fsVersionedType type) {
|
||||
ConstructorInfo[] publicConstructors = type.ModelType.GetDeclaredConstructors();
|
||||
|
||||
for (int i = 0; i < type.Ancestors.Length; ++i) {
|
||||
Type requiredConstructorType = type.Ancestors[i].ModelType;
|
||||
|
||||
bool found = false;
|
||||
for (int j = 0; j < publicConstructors.Length; ++j) {
|
||||
var parameters = publicConstructors[j].GetParameters();
|
||||
if (parameters.Length == 1 && parameters[0].ParameterType == requiredConstructorType) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
throw new fsMissingVersionConstructorException(type.ModelType, requiredConstructorType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the given version graph contains only unique versions.
|
||||
/// </summary>
|
||||
private static void VerifyUniqueVersionStrings(fsVersionedType type) {
|
||||
// simple tree traversal
|
||||
|
||||
var found = new Dictionary<string, Type>();
|
||||
|
||||
var remaining = new Queue<fsVersionedType>();
|
||||
remaining.Enqueue(type);
|
||||
|
||||
while (remaining.Count > 0) {
|
||||
fsVersionedType item = remaining.Dequeue();
|
||||
|
||||
// Verify we do not already have the version string. Take into account that we're not just
|
||||
// comparing the same model twice, since we can have a valid import graph that has the same
|
||||
// model multiple times.
|
||||
if (found.ContainsKey(item.VersionString) && found[item.VersionString] != item.ModelType) {
|
||||
throw new fsDuplicateVersionNameException(found[item.VersionString], item.ModelType, item.VersionString);
|
||||
}
|
||||
found[item.VersionString] = item.ModelType;
|
||||
|
||||
// scan the ancestors as well
|
||||
foreach (var ancestor in item.Ancestors) {
|
||||
remaining.Enqueue(ancestor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6e2cbf05d62993b4c900b6f0568b5525
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,49 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public struct fsVersionedType {
|
||||
/// <summary>
|
||||
/// The direct ancestors that this type can import.
|
||||
/// </summary>
|
||||
public fsVersionedType[] Ancestors;
|
||||
|
||||
/// <summary>
|
||||
/// The identifying string that is unique among all ancestors.
|
||||
/// </summary>
|
||||
public string VersionString;
|
||||
|
||||
/// <summary>
|
||||
/// The modeling type that this versioned type maps back to.
|
||||
/// </summary>
|
||||
public Type ModelType;
|
||||
|
||||
/// <summary>
|
||||
/// Migrate from an instance of an ancestor.
|
||||
/// </summary>
|
||||
public object Migrate(object ancestorInstance) {
|
||||
return Activator.CreateInstance(ModelType, ancestorInstance);
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return "fsVersionedType [ModelType=" + ModelType + ", VersionString=" + VersionString + ", Ancestors.Length=" + Ancestors.Length + "]";
|
||||
}
|
||||
|
||||
public static bool operator ==(fsVersionedType a, fsVersionedType b) {
|
||||
return a.ModelType == b.ModelType;
|
||||
}
|
||||
|
||||
public static bool operator !=(fsVersionedType a, fsVersionedType b) {
|
||||
return a.ModelType != b.ModelType;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) {
|
||||
return
|
||||
obj is fsVersionedType &&
|
||||
ModelType == ((fsVersionedType)obj).ModelType;
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
return ModelType.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 98a8b020907c059448da9798c38f201d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e45b6257da83c52429dcde2ab7b7c7e4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,152 +0,0 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// A property or field on a MetaType. This unifies the FieldInfo and PropertyInfo classes.
|
||||
/// </summary>
|
||||
public class fsMetaProperty {
|
||||
internal fsMetaProperty(fsConfig config, FieldInfo field) {
|
||||
_memberInfo = field;
|
||||
StorageType = field.FieldType;
|
||||
MemberName = field.Name;
|
||||
IsPublic = field.IsPublic;
|
||||
IsReadOnly = field.IsInitOnly;
|
||||
CanRead = true;
|
||||
CanWrite = true;
|
||||
|
||||
CommonInitialize(config);
|
||||
}
|
||||
|
||||
internal fsMetaProperty(fsConfig config, PropertyInfo property) {
|
||||
_memberInfo = property;
|
||||
StorageType = property.PropertyType;
|
||||
MemberName = property.Name;
|
||||
IsPublic = (property.GetGetMethod() != null && property.GetGetMethod().IsPublic) &&
|
||||
(property.GetSetMethod() != null && property.GetSetMethod().IsPublic);
|
||||
IsReadOnly = false;
|
||||
CanRead = property.CanRead;
|
||||
CanWrite = property.CanWrite;
|
||||
|
||||
CommonInitialize(config);
|
||||
}
|
||||
|
||||
private void CommonInitialize(fsConfig config) {
|
||||
var attr = fsPortableReflection.GetAttribute<fsPropertyAttribute>(_memberInfo);
|
||||
if (attr != null) {
|
||||
JsonName = attr.Name;
|
||||
OverrideConverterType = attr.Converter;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(JsonName)) {
|
||||
JsonName = config.GetJsonNameFromMemberName(MemberName, _memberInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal handle to the reflected member.
|
||||
/// </summary>
|
||||
private MemberInfo _memberInfo;
|
||||
|
||||
/// <summary>
|
||||
/// The type of value that is stored inside of the property. For example, for an int field,
|
||||
/// StorageType will be typeof(int).
|
||||
/// </summary>
|
||||
public Type StorageType {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A custom fsBaseConverter instance to use for this field/property, if requested. This will be
|
||||
/// null if the default converter selection algorithm should be used. This is specified using the
|
||||
/// [fsObject] annotation with the Converter field.
|
||||
/// </summary>
|
||||
public Type OverrideConverterType {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can this property be read?
|
||||
/// </summary>
|
||||
public bool CanRead {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can this property be written to?
|
||||
/// </summary>
|
||||
public bool CanWrite {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The serialized name of the property, as it should appear in JSON.
|
||||
/// </summary>
|
||||
public string JsonName {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the actual member.
|
||||
/// </summary>
|
||||
public string MemberName {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this member public?
|
||||
/// </summary>
|
||||
public bool IsPublic {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this type readonly? We can modify readonly properties using reflection, but not
|
||||
/// using generated C#.
|
||||
/// </summary>
|
||||
public bool IsReadOnly {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a value to the property that this MetaProperty represents, using given object
|
||||
/// instance as the context.
|
||||
/// </summary>
|
||||
public void Write(object context, object value) {
|
||||
FieldInfo field = _memberInfo as FieldInfo;
|
||||
PropertyInfo property = _memberInfo as PropertyInfo;
|
||||
|
||||
if (field != null) {
|
||||
field.SetValue(context, value);
|
||||
}
|
||||
|
||||
else if (property != null) {
|
||||
MethodInfo setMethod = property.GetSetMethod(/*nonPublic:*/ true);
|
||||
if (setMethod != null) {
|
||||
setMethod.Invoke(context, new object[] { value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a value from the property that this MetaProperty represents, using the given
|
||||
/// object instance as the context.
|
||||
/// </summary>
|
||||
public object Read(object context) {
|
||||
if (_memberInfo is PropertyInfo) {
|
||||
return ((PropertyInfo)_memberInfo).GetValue(context, new object[] { });
|
||||
}
|
||||
|
||||
else {
|
||||
return ((FieldInfo)_memberInfo).GetValue(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9bb14b7a131d5a44693d3005bd480781
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,336 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FullSerializer.Internal;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// MetaType contains metadata about a type. This is used by the reflection serializer.
|
||||
/// </summary>
|
||||
public class fsMetaType {
|
||||
private static Dictionary<fsConfig, Dictionary<Type, fsMetaType>> _configMetaTypes =
|
||||
new Dictionary<fsConfig, Dictionary<Type, fsMetaType>>();
|
||||
|
||||
public static fsMetaType Get(fsConfig config, Type type) {
|
||||
Dictionary<Type, fsMetaType> metaTypes;
|
||||
if (_configMetaTypes.TryGetValue(config, out metaTypes) == false)
|
||||
metaTypes = _configMetaTypes[config] = new Dictionary<Type, fsMetaType>();
|
||||
|
||||
fsMetaType metaType;
|
||||
if (metaTypes.TryGetValue(type, out metaType) == false) {
|
||||
metaType = new fsMetaType(config, type);
|
||||
metaTypes[type] = metaType;
|
||||
}
|
||||
|
||||
return metaType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears out the cached type results. Useful if some prior assumptions become invalid, ie, the default member
|
||||
/// serialization mode.
|
||||
/// </summary>
|
||||
public static void ClearCache() {
|
||||
_configMetaTypes = new Dictionary<fsConfig, Dictionary<Type, fsMetaType>>();
|
||||
}
|
||||
|
||||
private fsMetaType(fsConfig config, Type reflectedType) {
|
||||
ReflectedType = reflectedType;
|
||||
|
||||
List<fsMetaProperty> properties = new List<fsMetaProperty>();
|
||||
CollectProperties(config, properties, reflectedType);
|
||||
Properties = properties.ToArray();
|
||||
}
|
||||
|
||||
public Type ReflectedType;
|
||||
|
||||
private static void CollectProperties(fsConfig config, List<fsMetaProperty> properties, Type reflectedType) {
|
||||
// do we require a [SerializeField] or [fsProperty] attribute?
|
||||
bool requireOptIn = config.DefaultMemberSerialization == fsMemberSerialization.OptIn;
|
||||
bool requireOptOut = config.DefaultMemberSerialization == fsMemberSerialization.OptOut;
|
||||
|
||||
fsObjectAttribute attr = fsPortableReflection.GetAttribute<fsObjectAttribute>(reflectedType);
|
||||
if (attr != null) {
|
||||
requireOptIn = attr.MemberSerialization == fsMemberSerialization.OptIn;
|
||||
requireOptOut = attr.MemberSerialization == fsMemberSerialization.OptOut;
|
||||
}
|
||||
|
||||
MemberInfo[] members = reflectedType.GetDeclaredMembers();
|
||||
foreach (var member in members) {
|
||||
// We don't serialize members annotated with any of the ignore serialize attributes
|
||||
if (config.IgnoreSerializeAttributes.Any(t => fsPortableReflection.HasAttribute(member, t))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PropertyInfo property = member as PropertyInfo;
|
||||
FieldInfo field = member as FieldInfo;
|
||||
|
||||
// Early out if it's neither a field or a property, since we don't serialize anything else.
|
||||
if (property == null && field == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip properties if we don't want them, to avoid the cost of checking attributes.
|
||||
if (property != null && !config.EnablePropertySerialization) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an opt-in annotation is required, then skip the property if it doesn't have one
|
||||
// of the serialize attributes
|
||||
if (requireOptIn &&
|
||||
!config.SerializeAttributes.Any(t => fsPortableReflection.HasAttribute(member, t))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an opt-out annotation is required, then skip the property *only if* it has one of
|
||||
// the not serialize attributes
|
||||
if (requireOptOut &&
|
||||
config.IgnoreSerializeAttributes.Any(t => fsPortableReflection.HasAttribute(member, t))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property != null) {
|
||||
if (CanSerializeProperty(config, property, members, requireOptOut)) {
|
||||
properties.Add(new fsMetaProperty(config, property));
|
||||
}
|
||||
}
|
||||
else if (field != null) {
|
||||
if (CanSerializeField(config, field, requireOptOut)) {
|
||||
properties.Add(new fsMetaProperty(config, field));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reflectedType.Resolve().BaseType != null) {
|
||||
CollectProperties(config, properties, reflectedType.Resolve().BaseType);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAutoProperty(PropertyInfo property, MemberInfo[] members) {
|
||||
return
|
||||
property.CanWrite && property.CanRead &&
|
||||
fsPortableReflection.HasAttribute(
|
||||
property.GetGetMethod(), typeof(CompilerGeneratedAttribute), /*shouldCache:*/false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the given property should be serialized.
|
||||
/// </summary>
|
||||
/// <param name="annotationFreeValue">Should a property without any annotations be serialized?</param>
|
||||
private static bool CanSerializeProperty(fsConfig config, PropertyInfo property, MemberInfo[] members, bool annotationFreeValue) {
|
||||
// We don't serialize delegates
|
||||
if (typeof(Delegate).IsAssignableFrom(property.PropertyType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var publicGetMethod = property.GetGetMethod(/*nonPublic:*/ false);
|
||||
var publicSetMethod = property.GetSetMethod(/*nonPublic:*/ false);
|
||||
|
||||
// We do not bother to serialize static fields.
|
||||
if ((publicGetMethod != null && publicGetMethod.IsStatic) ||
|
||||
(publicSetMethod != null && publicSetMethod.IsStatic)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Never serialize indexers. I can't think of a sane way to serialize/deserialize them, and they're normally wrappers around other fields anyway...
|
||||
if (property.GetIndexParameters().Length > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a property is annotated with one of the serializable attributes, then it should
|
||||
// it should definitely be serialized.
|
||||
//
|
||||
// NOTE: We place this override check *after* the static check, because we *never*
|
||||
// allow statics to be serialized.
|
||||
if (config.SerializeAttributes.Any(t => fsPortableReflection.HasAttribute(property, t))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the property cannot be both read and written to, we are not going to serialize it
|
||||
// regardless of the default serialization mode
|
||||
if (property.CanRead == false || property.CanWrite == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Depending on the configuration options, check whether the property is automatic
|
||||
// and if it has a public setter to determine whether it should be serialized
|
||||
if ((publicGetMethod != null && (config.SerializeNonPublicSetProperties || publicSetMethod != null)) &&
|
||||
(config.SerializeNonAutoProperties || IsAutoProperty(property, members))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, we don't bother with serialization
|
||||
return annotationFreeValue;
|
||||
}
|
||||
|
||||
private static bool CanSerializeField(fsConfig config, FieldInfo field, bool annotationFreeValue) {
|
||||
// We don't serialize delegates
|
||||
if (typeof(Delegate).IsAssignableFrom(field.FieldType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't serialize compiler generated fields.
|
||||
if (field.IsDefined(typeof(CompilerGeneratedAttribute), false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't serialize static fields
|
||||
if (field.IsStatic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We want to serialize any fields annotated with one of the serialize attributes.
|
||||
//
|
||||
// NOTE: This occurs *after* the static check, because we *never* want to serialize
|
||||
// static fields.
|
||||
if (config.SerializeAttributes.Any(t => fsPortableReflection.HasAttribute(field, t))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We use !IsPublic because that also checks for internal, protected, and private.
|
||||
if (!annotationFreeValue && !field.IsPublic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to emit an AOT compiled direct converter for this type.
|
||||
/// </summary>
|
||||
/// <returns>True if AOT data was emitted, false otherwise.</returns>
|
||||
public bool EmitAotData() {
|
||||
if (_hasEmittedAotData == false) {
|
||||
_hasEmittedAotData = true;
|
||||
|
||||
// NOTE:
|
||||
// Even if the type has derived types, we can still generate a direct converter for it.
|
||||
// Direct converters are not used for inherited types, so the reflected converter or something
|
||||
// similar will be used for the derived type instead of our AOT compiled one.
|
||||
|
||||
for (int i = 0; i < Properties.Length; ++i) {
|
||||
// Cannot AOT compile since we need to public member access.
|
||||
if (Properties[i].IsPublic == false)
|
||||
return false;
|
||||
// Cannot AOT compile since readonly members can only be modified using reflection.
|
||||
if (Properties[i].IsReadOnly)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot AOT compile since we need a default ctor.
|
||||
if (HasDefaultConstructor == false)
|
||||
return false;
|
||||
|
||||
fsAotCompilationManager.AddAotCompilation(ReflectedType, Properties, _isDefaultConstructorPublic);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private bool _hasEmittedAotData;
|
||||
|
||||
public fsMetaProperty[] Properties {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the type represented by this metadata contains a default constructor.
|
||||
/// </summary>
|
||||
public bool HasDefaultConstructor {
|
||||
get {
|
||||
if (_hasDefaultConstructorCache.HasValue == false) {
|
||||
// arrays are considered to have a default constructor
|
||||
if (ReflectedType.Resolve().IsArray) {
|
||||
_hasDefaultConstructorCache = true;
|
||||
_isDefaultConstructorPublic = true;
|
||||
}
|
||||
|
||||
// value types (ie, structs) always have a default constructor
|
||||
else if (ReflectedType.Resolve().IsValueType) {
|
||||
_hasDefaultConstructorCache = true;
|
||||
_isDefaultConstructorPublic = true;
|
||||
}
|
||||
|
||||
else {
|
||||
// consider private constructors as well
|
||||
var ctor = ReflectedType.GetDeclaredConstructor(fsPortableReflection.EmptyTypes);
|
||||
_hasDefaultConstructorCache = ctor != null;
|
||||
if (ctor != null) {
|
||||
_isDefaultConstructorPublic = ctor.IsPublic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _hasDefaultConstructorCache.Value;
|
||||
}
|
||||
}
|
||||
private bool? _hasDefaultConstructorCache;
|
||||
private bool _isDefaultConstructorPublic;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the type that this metadata points back to. If this type has a
|
||||
/// default constructor, then Activator.CreateInstance will be used to construct the type
|
||||
/// (or Array.CreateInstance if it an array). Otherwise, an uninitialized object created via
|
||||
/// FormatterServices.GetSafeUninitializedObject is used to construct the instance.
|
||||
/// </summary>
|
||||
public object CreateInstance() {
|
||||
if (ReflectedType.Resolve().IsInterface || ReflectedType.Resolve().IsAbstract) {
|
||||
throw new Exception("Cannot create an instance of an interface or abstract type for " + ReflectedType);
|
||||
}
|
||||
|
||||
#if !NO_UNITY
|
||||
// Unity requires special construction logic for types that derive from
|
||||
// ScriptableObject.
|
||||
if (typeof(UnityEngine.ScriptableObject).IsAssignableFrom(ReflectedType)) {
|
||||
return UnityEngine.ScriptableObject.CreateInstance(ReflectedType);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Strings don't have default constructors but also fail when run through
|
||||
// FormatterSerivces.GetSafeUninitializedObject
|
||||
if (typeof(string) == ReflectedType) {
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (HasDefaultConstructor == false) {
|
||||
#if !UNITY_EDITOR && (UNITY_WEBPLAYER || UNITY_WP8 || UNITY_METRO)
|
||||
throw new InvalidOperationException("The selected Unity platform requires " +
|
||||
ReflectedType.FullName + " to have a default constructor. Please add one.");
|
||||
#else
|
||||
return System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(ReflectedType);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ReflectedType.Resolve().IsArray) {
|
||||
// we have to start with a size zero array otherwise it will have invalid data
|
||||
// inside of it
|
||||
return Array.CreateInstance(ReflectedType.GetElementType(), 0);
|
||||
}
|
||||
|
||||
try {
|
||||
#if (!UNITY_EDITOR && (UNITY_METRO))
|
||||
// In WinRT/WinStore builds, Activator.CreateInstance(..., true) is broken
|
||||
return Activator.CreateInstance(ReflectedType);
|
||||
#else
|
||||
return Activator.CreateInstance(ReflectedType, /*nonPublic:*/ true);
|
||||
#endif
|
||||
}
|
||||
#if (!UNITY_EDITOR && (UNITY_METRO)) == false
|
||||
catch (MissingMethodException e) {
|
||||
throw new InvalidOperationException("Unable to create instance of " + ReflectedType + "; there is no default constructor", e);
|
||||
}
|
||||
#endif
|
||||
catch (TargetInvocationException e) {
|
||||
throw new InvalidOperationException("Constructor of " + ReflectedType + " threw an exception when creating an instance", e);
|
||||
}
|
||||
catch (MemberAccessException e) {
|
||||
throw new InvalidOperationException("Unable to access constructor of " + ReflectedType, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f5bc83526ccd76f4c877c4db426b7e9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,49 +0,0 @@
|
|||
using System;
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WSA
|
||||
// For System.Reflection.TypeExtensions
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public static class fsReflectionUtility {
|
||||
/// <summary>
|
||||
/// Searches for a particular implementation of the given interface type inside of the type.
|
||||
/// This is particularly useful if the interface type is an open type, ie, typeof(IFace{}),
|
||||
/// because this method will then return IFace{} but with appropriate type parameters
|
||||
/// inserted.
|
||||
/// </summary>
|
||||
/// <param name="type">The base type to search for interface</param>
|
||||
/// <param name="interfaceType">The interface type to search for. Can be an open generic
|
||||
/// type.</param>
|
||||
/// <returns>The actual interface type that the type contains, or null if there is no
|
||||
/// implementation of the given interfaceType on type.</returns>
|
||||
public static Type GetInterface(Type type, Type interfaceType) {
|
||||
if (interfaceType.Resolve().IsGenericType &&
|
||||
interfaceType.Resolve().IsGenericTypeDefinition == false) {
|
||||
|
||||
throw new ArgumentException("GetInterface requires that if the interface " +
|
||||
"type is generic, then it must be the generic type definition, not a " +
|
||||
"specific generic type instantiation");
|
||||
};
|
||||
|
||||
while (type != null) {
|
||||
foreach (var iface in type.GetInterfaces()) {
|
||||
if (iface.Resolve().IsGenericType) {
|
||||
if (interfaceType == iface.GetGenericTypeDefinition()) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
else if (interfaceType == iface) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
type = type.Resolve().BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b4280b980c130b42a320f8b5fdfeff5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,167 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
/// <summary>
|
||||
/// Caches type name to type lookups. Type lookups occur in all loaded assemblies.
|
||||
/// </summary>
|
||||
public static class fsTypeCache {
|
||||
/// <summary>
|
||||
/// Cache from fully qualified type name to type instances.
|
||||
/// </summary>
|
||||
// TODO: verify that type names will be unique
|
||||
private static Dictionary<string, Type> _cachedTypes = new Dictionary<string, Type>();
|
||||
|
||||
/// <summary>
|
||||
/// Assemblies indexed by their name.
|
||||
/// </summary>
|
||||
private static Dictionary<string, Assembly> _assembliesByName;
|
||||
|
||||
/// <summary>
|
||||
/// A list of assemblies, by index.
|
||||
/// </summary>
|
||||
private static List<Assembly> _assembliesByIndex;
|
||||
|
||||
static fsTypeCache() {
|
||||
// Setup assembly references so searching and the like resolves correctly.
|
||||
_assembliesByName = new Dictionary<string, Assembly>();
|
||||
_assembliesByIndex = new List<Assembly>();
|
||||
|
||||
#if (!UNITY_EDITOR && UNITY_METRO && !ENABLE_IL2CPP) // no AppDomain on WinRT
|
||||
var assembly = typeof(object).GetTypeInfo().Assembly;
|
||||
_assembliesByName[assembly.FullName] = assembly;
|
||||
_assembliesByIndex.Add(assembly);
|
||||
#else
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
|
||||
_assembliesByName[assembly.FullName] = assembly;
|
||||
_assembliesByIndex.Add(assembly);
|
||||
}
|
||||
#endif
|
||||
|
||||
_cachedTypes = new Dictionary<string, Type>();
|
||||
|
||||
#if !(UNITY_WP8 || UNITY_METRO) // AssemblyLoad events are not supported on these platforms
|
||||
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !(UNITY_WP8 || UNITY_METRO) // AssemblyLoad events are not supported on these platforms
|
||||
private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args) {
|
||||
_assembliesByName[args.LoadedAssembly.FullName] = args.LoadedAssembly;
|
||||
_assembliesByIndex.Add(args.LoadedAssembly);
|
||||
|
||||
_cachedTypes = new Dictionary<string, Type>();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Does a direct lookup for the given type, ie, goes directly to the assembly identified by
|
||||
/// assembly name and finds it there.
|
||||
/// </summary>
|
||||
/// <param name="assemblyName">The assembly to find the type in.</param>
|
||||
/// <param name="typeName">The name of the type.</param>
|
||||
/// <param name="type">The found type.</param>
|
||||
/// <returns>True if the type was found, false otherwise.</returns>
|
||||
private static bool TryDirectTypeLookup(string assemblyName, string typeName, out Type type) {
|
||||
if (assemblyName != null) {
|
||||
Assembly assembly;
|
||||
if (_assembliesByName.TryGetValue(assemblyName, out assembly)) {
|
||||
type = assembly.GetType(typeName, /*throwOnError:*/ false);
|
||||
return type != null;
|
||||
}
|
||||
}
|
||||
|
||||
type = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to do an indirect type lookup by scanning through every loaded assembly until the
|
||||
/// type is found in one of them.
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the type.</param>
|
||||
/// <param name="type">The found type.</param>
|
||||
/// <returns>True if the type was found, false otherwise.</returns>
|
||||
private static bool TryIndirectTypeLookup(string typeName, out Type type) {
|
||||
// There used to be a foreach loop through the value keys of the _assembliesByName
|
||||
// dictionary. However, during that loop assembly loads could occur, causing an
|
||||
// OutOfSync exception. To resolve that, we just iterate through the assemblies by
|
||||
// index.
|
||||
|
||||
int i = 0;
|
||||
while (i < _assembliesByIndex.Count) {
|
||||
Assembly assembly = _assembliesByIndex[i];
|
||||
|
||||
// try GetType; should be fast
|
||||
type = assembly.GetType(typeName);
|
||||
if (type != null) {
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
// This code here is slow and is just here as a fallback
|
||||
while (i < _assembliesByIndex.Count) {
|
||||
Assembly assembly = _assembliesByIndex[i];
|
||||
|
||||
// private type or similar; go through the slow path and check every type's full
|
||||
// name
|
||||
foreach (var foundType in assembly.GetTypes()) {
|
||||
if (foundType.FullName == typeName) {
|
||||
type = foundType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
type = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any cached type lookup results.
|
||||
/// </summary>
|
||||
public static void Reset() {
|
||||
_cachedTypes = new Dictionary<string, Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a type with the given name. An exception is thrown if no type with the given name
|
||||
/// can be found. This method searches all currently loaded assemblies for the given type. If the type cannot
|
||||
/// be found, then null will be returned.
|
||||
/// </summary>
|
||||
/// <param name="name">The fully qualified name of the type.</param>
|
||||
public static Type GetType(string name) {
|
||||
return GetType(name, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a type with the given name. An exception is thrown if no type with the given name
|
||||
/// can be found. This method searches all currently loaded assemblies for the given type. If the type cannot
|
||||
/// be found, then null will be returned.
|
||||
/// </summary>
|
||||
/// <param name="name">The fully qualified name of the type.</param>
|
||||
/// <param name="assemblyHint">A hint for the assembly to start the search with. Use null if unknown.</param>
|
||||
public static Type GetType(string name, string assemblyHint) {
|
||||
if (string.IsNullOrEmpty(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type;
|
||||
if (_cachedTypes.TryGetValue(name, out type) == false) {
|
||||
// if both the direct and indirect type lookups fail, then throw an exception
|
||||
if (TryDirectTypeLookup(assemblyHint, name, out type) == false &&
|
||||
TryIndirectTypeLookup(name, out type) == false) {
|
||||
}
|
||||
|
||||
_cachedTypes[name] = type;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 233490e64cba5c2408b26b49bd077483
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,132 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FullSerializer.Internal;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The AOT compilation manager
|
||||
/// </summary>
|
||||
public class fsAotCompilationManager {
|
||||
/// <summary>
|
||||
/// Ahead of time compilations that are available. The type maps to the object type the generated converter
|
||||
/// will serialize/deserialize, and the string is the text content for a converter that will do the serialization.
|
||||
/// <para />
|
||||
/// The generated serializer is completely independent and you don't need to do anything. Simply add the file to
|
||||
/// your project and it'll get used instead of the reflection based one.
|
||||
/// </summary>
|
||||
public static Dictionary<Type, string> AvailableAotCompilations {
|
||||
get {
|
||||
for (int i = 0; i < _uncomputedAotCompilations.Count; ++i) {
|
||||
var item = _uncomputedAotCompilations[i];
|
||||
_computedAotCompilations[item.Type] = GenerateDirectConverterForTypeInCSharp(item.Type, item.Members, item.IsConstructorPublic);
|
||||
}
|
||||
_uncomputedAotCompilations.Clear();
|
||||
|
||||
return _computedAotCompilations;
|
||||
}
|
||||
}
|
||||
private static Dictionary<Type, string> _computedAotCompilations = new Dictionary<Type, string>();
|
||||
|
||||
private struct AotCompilation {
|
||||
public Type Type;
|
||||
public fsMetaProperty[] Members;
|
||||
public bool IsConstructorPublic;
|
||||
}
|
||||
private static List<AotCompilation> _uncomputedAotCompilations = new List<AotCompilation>();
|
||||
|
||||
/// <summary>
|
||||
/// This is a helper method that makes it simple to run an AOT compilation on the given type.
|
||||
/// </summary>
|
||||
/// <param name="config">The configuration to use when running AOT compilation.</param>
|
||||
/// <param name="type">The type to perform the AOT compilation on.</param>
|
||||
/// <param name="aotCompiledClassInCSharp">The AOT class. Add this C# code to your project.</param>
|
||||
/// <returns>True if AOT compilation was successful.</returns>
|
||||
public static bool TryToPerformAotCompilation(fsConfig config, Type type, out string aotCompiledClassInCSharp) {
|
||||
if (fsMetaType.Get(config, type).EmitAotData()) {
|
||||
aotCompiledClassInCSharp = AvailableAotCompilations[type];
|
||||
return true;
|
||||
}
|
||||
|
||||
aotCompiledClassInCSharp = default(string);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new AOT compilation unit.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of object we are AOT compiling.</param>
|
||||
/// <param name="members">The members on the object which will be serialized/deserialized.</param>
|
||||
public static void AddAotCompilation(Type type, fsMetaProperty[] members, bool isConstructorPublic) {
|
||||
_uncomputedAotCompilations.Add(new AotCompilation {
|
||||
Type = type,
|
||||
Members = members,
|
||||
IsConstructorPublic = isConstructorPublic
|
||||
});
|
||||
}
|
||||
|
||||
private static string GetConverterString(fsMetaProperty member) {
|
||||
if (member.OverrideConverterType == null)
|
||||
return "null";
|
||||
|
||||
return string.Format("typeof({0})",
|
||||
member.OverrideConverterType.CSharpName(/*includeNamespace:*/ true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AOT compiles the object (in C#).
|
||||
/// </summary>
|
||||
private static string GenerateDirectConverterForTypeInCSharp(Type type, fsMetaProperty[] members, bool isConstructorPublic) {
|
||||
var sb = new StringBuilder();
|
||||
string typeName = type.CSharpName(/*includeNamespace:*/ true);
|
||||
string typeNameSafeDecl = type.CSharpName(true, true);
|
||||
|
||||
sb.AppendLine("using System;");
|
||||
sb.AppendLine("using System.Collections.Generic;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("namespace FullSerializer {");
|
||||
sb.AppendLine(" partial class fsConverterRegistrar {");
|
||||
sb.AppendLine(" public static Speedup." + typeNameSafeDecl + "_DirectConverter " + "Register_" + typeNameSafeDecl + ";");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("namespace FullSerializer.Speedup {");
|
||||
sb.AppendLine(" public class " + typeNameSafeDecl + "_DirectConverter : fsDirectConverter<" + typeName + "> {");
|
||||
sb.AppendLine(" protected override fsResult DoSerialize(" + typeName + " model, Dictionary<string, fsData> serialized) {");
|
||||
sb.AppendLine(" var result = fsResult.Success;");
|
||||
sb.AppendLine();
|
||||
foreach (var member in members) {
|
||||
sb.AppendLine(" result += SerializeMember(serialized, " + GetConverterString(member) + ", \"" + member.JsonName + "\", model." + member.MemberName + ");");
|
||||
}
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" return result;");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref " + typeName + " model) {");
|
||||
sb.AppendLine(" var result = fsResult.Success;");
|
||||
sb.AppendLine();
|
||||
for (int i = 0; i < members.Length; ++i) {
|
||||
var member = members[i];
|
||||
sb.AppendLine(" var t" + i + " = model." + member.MemberName + ";");
|
||||
sb.AppendLine(" result += DeserializeMember(data, " + GetConverterString(member) + ", \"" + member.JsonName + "\", out t" + i + ");");
|
||||
sb.AppendLine(" model." + member.MemberName + " = t" + i + ";");
|
||||
sb.AppendLine();
|
||||
}
|
||||
sb.AppendLine(" return result;");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" public override object CreateInstance(fsData data, Type storageType) {");
|
||||
if (isConstructorPublic) {
|
||||
sb.AppendLine(" return new " + typeName + "();");
|
||||
}
|
||||
else {
|
||||
sb.AppendLine(" return Activator.CreateInstance(typeof(" + typeName + "), /*nonPublic:*/true);");
|
||||
}
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 38f69a9d341a14246879983c2113fc43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,119 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FullSerializer.Internal;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The serialization converter allows for customization of the serialization process.
|
||||
/// </summary>
|
||||
/// <remarks>You do not want to derive from this class - there is no way to actually use it within
|
||||
/// the serializer.. Instead, derive from either fsConverter or fsDirectConverter</remarks>
|
||||
public abstract class fsBaseConverter {
|
||||
/// <summary>
|
||||
/// The serializer that was owns this converter.
|
||||
/// </summary>
|
||||
public fsSerializer Serializer;
|
||||
|
||||
/// <summary>
|
||||
/// Construct an object instance that will be passed to TryDeserialize. This should **not**
|
||||
/// deserialize the object.
|
||||
/// </summary>
|
||||
/// <param name="data">The data the object was serialized with.</param>
|
||||
/// <param name="storageType">The field/property type that is storing the instance.</param>
|
||||
/// <returns>An object instance</returns>
|
||||
public virtual object CreateInstance(fsData data, Type storageType) {
|
||||
if (RequestCycleSupport(storageType)) {
|
||||
throw new InvalidOperationException("Please override CreateInstance for " +
|
||||
GetType().FullName + "; the object graph for " + storageType +
|
||||
" can contain potentially contain cycles, so separated instance creation " +
|
||||
"is needed");
|
||||
}
|
||||
|
||||
return storageType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, then the serializer will support cyclic references with the given converted
|
||||
/// type.
|
||||
/// </summary>
|
||||
/// <param name="storageType">The field/property type that is currently storing the object
|
||||
/// that is being serialized.</param>
|
||||
public virtual bool RequestCycleSupport(Type storageType) {
|
||||
if (storageType == typeof(string)) return false;
|
||||
|
||||
return storageType.Resolve().IsClass || storageType.Resolve().IsInterface;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, then the serializer will include inheritance data for the given converter.
|
||||
/// </summary>
|
||||
/// <param name="storageType">The field/property type that is currently storing the object
|
||||
/// that is being serialized.</param>
|
||||
public virtual bool RequestInheritanceSupport(Type storageType) {
|
||||
return storageType.Resolve().IsSealed == false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the actual object into the given data storage.
|
||||
/// </summary>
|
||||
/// <param name="instance">The object instance to serialize. This will never be null.</param>
|
||||
/// <param name="serialized">The serialized state.</param>
|
||||
/// <param name="storageType">The field/property type that is storing this instance.</param>
|
||||
/// <returns>If serialization was successful.</returns>
|
||||
public abstract fsResult TrySerialize(object instance, out fsData serialized, Type storageType);
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize data into the object instance.
|
||||
/// </summary>
|
||||
/// <param name="data">Serialization data to deserialize from.</param>
|
||||
/// <param name="instance">The object instance to deserialize into.</param>
|
||||
/// <param name="storageType">The field/property type that is storing the instance.</param>
|
||||
/// <returns>True if serialization was successful, false otherwise.</returns>
|
||||
public abstract fsResult TryDeserialize(fsData data, ref object instance, Type storageType);
|
||||
|
||||
protected fsResult FailExpectedType(fsData data, params fsDataType[] types) {
|
||||
return fsResult.Fail(GetType().Name + " expected one of " +
|
||||
string.Join(", ", types.Select(t => t.ToString()).ToArray()) +
|
||||
" but got " + data.Type + " in " + data);
|
||||
}
|
||||
|
||||
protected fsResult CheckType(fsData data, fsDataType type) {
|
||||
if (data.Type != type) {
|
||||
return fsResult.Fail(GetType().Name + " expected " + type + " but got " + data.Type + " in " + data);
|
||||
}
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
protected fsResult CheckKey(fsData data, string key, out fsData subitem) {
|
||||
return CheckKey(data.AsDictionary, key, out subitem);
|
||||
}
|
||||
|
||||
protected fsResult CheckKey(Dictionary<string, fsData> data, string key, out fsData subitem) {
|
||||
if (data.TryGetValue(key, out subitem) == false) {
|
||||
return fsResult.Fail(GetType().Name + " requires a <" + key + "> key in the data " + data);
|
||||
}
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
protected fsResult SerializeMember<T>(Dictionary<string, fsData> data, Type overrideConverterType, string name, T value) {
|
||||
fsData memberData;
|
||||
var result = Serializer.TrySerialize(typeof(T), overrideConverterType, value, out memberData);
|
||||
if (result.Succeeded) data[name] = memberData;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected fsResult DeserializeMember<T>(Dictionary<string, fsData> data, Type overrideConverterType, string name, out T value) {
|
||||
fsData memberData;
|
||||
if (data.TryGetValue(name, out memberData) == false) {
|
||||
value = default(T);
|
||||
return fsResult.Fail("Unable to find member \"" + name + "\"");
|
||||
}
|
||||
|
||||
object storage = null;
|
||||
var result = Serializer.TryDeserialize(memberData, typeof(T), overrideConverterType, ref storage);
|
||||
value = (T)storage;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8a9a1beed27909d48aa194777a3c7181
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,94 +0,0 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FullSerializer {
|
||||
// Global configuration options.
|
||||
public static class fsGlobalConfig {
|
||||
/// <summary>
|
||||
/// Should deserialization be case sensitive? If this is false and the JSON has multiple members with the
|
||||
/// same keys only separated by case, then this results in undefined behavior.
|
||||
/// </summary>
|
||||
public static bool IsCaseSensitive = true;
|
||||
|
||||
/// <summary>
|
||||
/// If exceptions are allowed internally, then additional date formats can be deserialized.
|
||||
/// Note that the Full Serializer public API will *not* throw exceptions with this enabled;
|
||||
/// errors will still be returned in a fsResult instance.
|
||||
/// </summary>
|
||||
public static bool AllowInternalExceptions = true;
|
||||
|
||||
/// <summary>
|
||||
/// This string will be used to prefix fields used internally by FullSerializer.
|
||||
/// </summary>
|
||||
public static string InternalFieldPrefix = "$";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables some top-level customization of Full Serializer.
|
||||
/// </summary>
|
||||
public class fsConfig {
|
||||
/// <summary>
|
||||
/// The attributes that will force a field or property to be serialized.
|
||||
/// </summary>
|
||||
public Type[] SerializeAttributes = {
|
||||
#if !NO_UNITY
|
||||
typeof(UnityEngine.SerializeField),
|
||||
#endif
|
||||
typeof(fsPropertyAttribute)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The attributes that will force a field or property to *not* be serialized.
|
||||
/// </summary>
|
||||
public Type[] IgnoreSerializeAttributes = { typeof(NonSerializedAttribute), typeof(fsIgnoreAttribute) };
|
||||
|
||||
/// <summary>
|
||||
/// The default member serialization.
|
||||
/// </summary>
|
||||
public fsMemberSerialization DefaultMemberSerialization = fsMemberSerialization.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a C# field/property name into the key used for the JSON object. For example, you could
|
||||
/// force all JSON names to lowercase with:
|
||||
///
|
||||
/// fsConfig.GetJsonNameFromMemberName = (name, info) => name.ToLower();
|
||||
///
|
||||
/// This will only be used when the name is not explicitly specified with fsProperty.
|
||||
/// </summary>
|
||||
public Func<string, MemberInfo, string> GetJsonNameFromMemberName = (name, info) => name;
|
||||
|
||||
/// <summary>
|
||||
/// If false, then *all* property serialization support will be disabled - even properties
|
||||
/// explicitly annotated with fsProperty or any other opt-in annotation.
|
||||
///
|
||||
/// Setting this to false means that SerializeNonAutoProperties and
|
||||
/// SerializeNonPublicSetProperties will be completely ignored.
|
||||
/// </summary>
|
||||
public bool EnablePropertySerialization = true;
|
||||
|
||||
/// <summary>
|
||||
/// Should the default serialization behaviour include non-auto properties?
|
||||
/// </summary>
|
||||
public bool SerializeNonAutoProperties = false;
|
||||
|
||||
/// <summary>
|
||||
/// Should the default serialization behaviour include properties with non-public setters?
|
||||
/// </summary>
|
||||
public bool SerializeNonPublicSetProperties = true;
|
||||
|
||||
/// <summary>
|
||||
/// If not null, this string format will be used for DateTime instead of the default one.
|
||||
/// </summary>
|
||||
public string CustomDateTimeFormatString = null;
|
||||
|
||||
/// <summary>
|
||||
/// Int64 and UInt64 will be serialized and deserialized as string for compatibility
|
||||
/// </summary>
|
||||
public bool Serialize64BitIntegerAsString = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enums are serialized using their names by default. Setting this to true will serialize them as integers instead.
|
||||
/// </summary>
|
||||
public bool SerializeEnumsAsInteger = false;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 76108d7346331af428d2c9393d9d8027
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,47 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// fsContext stores global metadata that can be used to customize how fsConverters operate
|
||||
/// during serialization.
|
||||
/// </summary>
|
||||
public sealed class fsContext {
|
||||
/// <summary>
|
||||
/// All of the context objects.
|
||||
/// </summary>
|
||||
private readonly Dictionary<Type, object> _contextObjects = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Removes all context objects from the context.
|
||||
/// </summary>
|
||||
public void Reset() {
|
||||
_contextObjects.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the context object for the given type with the given value.
|
||||
/// </summary>
|
||||
public void Set<T>(T obj) {
|
||||
_contextObjects[typeof(T)] = obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if there is a context object for the given type.
|
||||
/// </summary>
|
||||
public bool Has<T>() {
|
||||
return _contextObjects.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the context object for the given type.
|
||||
/// </summary>
|
||||
public T Get<T>() {
|
||||
object val;
|
||||
if (_contextObjects.TryGetValue(typeof(T), out val)) {
|
||||
return (T)val;
|
||||
}
|
||||
throw new InvalidOperationException("There is no context object of type " + typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aa2d584506920bc42a437736d0eac8e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The serialization converter allows for customization of the serialization process.
|
||||
/// </summary>
|
||||
public abstract class fsConverter : fsBaseConverter {
|
||||
/// <summary>
|
||||
/// Can this converter serialize and deserialize the given object type?
|
||||
/// </summary>
|
||||
/// <param name="type">The given object type.</param>
|
||||
/// <returns>True if the converter can serialize it, false otherwise.</returns>
|
||||
public abstract bool CanProcess(Type type);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bba5af2bf7ead1c44b8ae89fc6f30783
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,36 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FullSerializer.Internal;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// This class allows arbitrary code to easily register global converters. To add a converter,
|
||||
/// simply declare a new field called "Register_*" that stores the type of converter you would
|
||||
/// like to add. Alternatively, you can do the same with a method called "Register_*"; just add
|
||||
/// the converter type to the `Converters` list.
|
||||
/// </summary>
|
||||
public partial class fsConverterRegistrar {
|
||||
static fsConverterRegistrar() {
|
||||
Converters = new List<Type>();
|
||||
|
||||
foreach (var field in typeof(fsConverterRegistrar).GetDeclaredFields()) {
|
||||
if (field.Name.StartsWith("Register_")) Converters.Add(field.FieldType);
|
||||
}
|
||||
|
||||
foreach (var method in typeof(fsConverterRegistrar).GetDeclaredMethods()) {
|
||||
if (method.Name.StartsWith("Register_")) method.Invoke(null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static List<Type> Converters;
|
||||
|
||||
// Example field registration:
|
||||
//public static AnimationCurve_DirectConverter Register_AnimationCurve_DirectConverter;
|
||||
|
||||
// Example method registration:
|
||||
//public static void Register_AnimationCurve_DirectConverter() {
|
||||
// Converters.Add(typeof(AnimationCurve_DirectConverter));
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ba7cbc3359b9f5439201a47840eba3a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,394 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The actual type that a JsonData instance can store.
|
||||
/// </summary>
|
||||
public enum fsDataType {
|
||||
Array,
|
||||
Object,
|
||||
Double,
|
||||
Int64,
|
||||
Boolean,
|
||||
String,
|
||||
Null
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A union type that stores a serialized value. The stored type can be one of six different
|
||||
/// types: null, boolean, double, Int64, string, Dictionary, or List.
|
||||
/// </summary>
|
||||
public sealed class fsData {
|
||||
/// <summary>
|
||||
/// The raw value that this serialized data stores. It can be one of six different types; a
|
||||
/// boolean, a double, Int64, a string, a Dictionary, or a List.
|
||||
/// </summary>
|
||||
private object _value;
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds null.
|
||||
/// </summary>
|
||||
public fsData() {
|
||||
_value = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds a boolean.
|
||||
/// </summary>
|
||||
public fsData(bool boolean) {
|
||||
_value = boolean;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds a double.
|
||||
/// </summary>
|
||||
public fsData(double f) {
|
||||
_value = f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fsData instance that holds an integer.
|
||||
/// </summary>
|
||||
public fsData(Int64 i) {
|
||||
_value = i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds a string.
|
||||
/// </summary>
|
||||
public fsData(string str) {
|
||||
_value = str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds a dictionary of values.
|
||||
/// </summary>
|
||||
public fsData(Dictionary<string, fsData> dict) {
|
||||
_value = dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fsData instance that holds a list of values.
|
||||
/// </summary>
|
||||
public fsData(List<fsData> list) {
|
||||
_value = list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a fsData instance that holds a dictionary.
|
||||
/// </summary>
|
||||
public static fsData CreateDictionary() {
|
||||
return new fsData(new Dictionary<string, fsData>(
|
||||
fsGlobalConfig.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a fsData instance that holds a list.
|
||||
/// </summary>
|
||||
public static fsData CreateList() {
|
||||
return new fsData(new List<fsData>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a fsData instance that holds a list with the initial capacity.
|
||||
/// </summary>
|
||||
public static fsData CreateList(int capacity) {
|
||||
return new fsData(new List<fsData>(capacity));
|
||||
}
|
||||
|
||||
public readonly static fsData True = new fsData(true);
|
||||
public readonly static fsData False = new fsData(false);
|
||||
public readonly static fsData Null = new fsData();
|
||||
#endregion
|
||||
|
||||
#region Internal Helper Methods
|
||||
/// <summary>
|
||||
/// Transforms the internal fsData instance into a dictionary.
|
||||
/// </summary>
|
||||
internal void BecomeDictionary() {
|
||||
_value = new Dictionary<string, fsData>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a shallow clone of this data instance.
|
||||
/// </summary>
|
||||
internal fsData Clone() {
|
||||
var clone = new fsData();
|
||||
clone._value = _value;
|
||||
return clone;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Casting Predicates
|
||||
public fsDataType Type {
|
||||
get {
|
||||
if (_value == null) return fsDataType.Null;
|
||||
if (_value is double) return fsDataType.Double;
|
||||
if (_value is Int64) return fsDataType.Int64;
|
||||
if (_value is bool) return fsDataType.Boolean;
|
||||
if (_value is string) return fsDataType.String;
|
||||
if (_value is Dictionary<string, fsData>) return fsDataType.Object;
|
||||
if (_value is List<fsData>) return fsDataType.Array;
|
||||
|
||||
throw new InvalidOperationException("unknown JSON data type");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to null.
|
||||
/// </summary>
|
||||
public bool IsNull {
|
||||
get {
|
||||
return _value == null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to a double.
|
||||
/// </summary>
|
||||
public bool IsDouble {
|
||||
get {
|
||||
return _value is double;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to an Int64.
|
||||
/// </summary>
|
||||
public bool IsInt64 {
|
||||
get {
|
||||
return _value is Int64;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to a boolean.
|
||||
/// </summary>
|
||||
public bool IsBool {
|
||||
get {
|
||||
return _value is bool;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to a string.
|
||||
/// </summary>
|
||||
public bool IsString {
|
||||
get {
|
||||
return _value is string;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to a Dictionary.
|
||||
/// </summary>
|
||||
public bool IsDictionary {
|
||||
get {
|
||||
return _value is Dictionary<string, fsData>;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this fsData instance maps back to a List.
|
||||
/// </summary>
|
||||
public bool IsList {
|
||||
get {
|
||||
return _value is List<fsData>;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Casts
|
||||
/// <summary>
|
||||
/// Casts this fsData to a double. Throws an exception if it is not a double.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public double AsDouble {
|
||||
get {
|
||||
return Cast<double>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Casts this fsData to an Int64. Throws an exception if it is not an Int64.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public Int64 AsInt64 {
|
||||
get {
|
||||
return Cast<Int64>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Casts this fsData to a boolean. Throws an exception if it is not a boolean.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public bool AsBool {
|
||||
get {
|
||||
return Cast<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Casts this fsData to a string. Throws an exception if it is not a string.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public string AsString {
|
||||
get {
|
||||
return Cast<string>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Casts this fsData to a Dictionary. Throws an exception if it is not a
|
||||
/// Dictionary.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public Dictionary<string, fsData> AsDictionary {
|
||||
get {
|
||||
return Cast<Dictionary<string, fsData>>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Casts this fsData to a List. Throws an exception if it is not a List.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public List<fsData> AsList {
|
||||
get {
|
||||
return Cast<List<fsData>>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper method to cast the underlying storage to the given type or throw a
|
||||
/// pretty printed exception on failure.
|
||||
/// </summary>
|
||||
private T Cast<T>() {
|
||||
if (_value is T) {
|
||||
return (T)_value;
|
||||
}
|
||||
|
||||
throw new InvalidCastException("Unable to cast <" + this + "> (with type = " +
|
||||
_value.GetType() + ") to type " + typeof(T));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString Implementation
|
||||
public override string ToString() {
|
||||
return fsJsonPrinter.CompressedJson(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Equality Comparisons
|
||||
/// <summary>
|
||||
/// Determines whether the specified object is equal to the current object.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) {
|
||||
return Equals(obj as fsData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified object is equal to the current object.
|
||||
/// </summary>
|
||||
public bool Equals(fsData other) {
|
||||
if (other == null || Type != other.Type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Type) {
|
||||
case fsDataType.Null:
|
||||
return true;
|
||||
|
||||
case fsDataType.Double:
|
||||
return AsDouble == other.AsDouble || Math.Abs(AsDouble - other.AsDouble) < double.Epsilon;
|
||||
|
||||
case fsDataType.Int64:
|
||||
return AsInt64 == other.AsInt64;
|
||||
|
||||
case fsDataType.Boolean:
|
||||
return AsBool == other.AsBool;
|
||||
|
||||
case fsDataType.String:
|
||||
return AsString == other.AsString;
|
||||
|
||||
case fsDataType.Array:
|
||||
var thisList = AsList;
|
||||
var otherList = other.AsList;
|
||||
|
||||
if (thisList.Count != otherList.Count) return false;
|
||||
|
||||
for (int i = 0; i < thisList.Count; ++i) {
|
||||
if (thisList[i].Equals(otherList[i]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case fsDataType.Object:
|
||||
var thisDict = AsDictionary;
|
||||
var otherDict = other.AsDictionary;
|
||||
|
||||
if (thisDict.Count != otherDict.Count) return false;
|
||||
|
||||
foreach (string key in thisDict.Keys) {
|
||||
if (otherDict.ContainsKey(key) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thisDict[key].Equals(otherDict[key]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Exception("Unknown data type");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true iff a == b.
|
||||
/// </summary>
|
||||
public static bool operator ==(fsData a, fsData b) {
|
||||
// If both are null, or both are same instance, return true.
|
||||
if (ReferenceEquals(a, b)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If one is null, but not both, return false.
|
||||
if (((object)a == null) || ((object)b == null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.IsDouble && b.IsDouble) {
|
||||
return Math.Abs(a.AsDouble - b.AsDouble) < double.Epsilon;
|
||||
}
|
||||
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true iff a != b.
|
||||
/// </summary>
|
||||
public static bool operator !=(fsData a, fsData b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data
|
||||
/// structures like a hash table.</returns>
|
||||
public override int GetHashCode() {
|
||||
return _value.GetHashCode();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f91f03a8b5894984aa6dcd1b7e60534e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,39 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The direct converter is similar to a regular converter, except that it targets specifically only one type.
|
||||
/// This means that it can be used without performance impact when discovering converters. It is strongly
|
||||
/// recommended that you derive from fsDirectConverter{TModel}.
|
||||
/// </summary>
|
||||
/// <remarks>Due to the way that direct converters operate, inheritance is *not* supported. Direct converters
|
||||
/// will only be used with the exact ModelType object.</remarks>
|
||||
public abstract class fsDirectConverter : fsBaseConverter {
|
||||
public abstract Type ModelType { get; }
|
||||
}
|
||||
|
||||
public abstract class fsDirectConverter<TModel> : fsDirectConverter {
|
||||
public override Type ModelType { get { return typeof(TModel); } }
|
||||
|
||||
public sealed override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
|
||||
var serializedDictionary = new Dictionary<string, fsData>();
|
||||
var result = DoSerialize((TModel)instance, serializedDictionary);
|
||||
serialized = new fsData(serializedDictionary);
|
||||
return result;
|
||||
}
|
||||
|
||||
public sealed override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
|
||||
var result = fsResult.Success;
|
||||
if ((result += CheckType(data, fsDataType.Object)).Failed) return result;
|
||||
|
||||
var obj = (TModel)instance;
|
||||
result += DoDeserialize(data.AsDictionary, ref obj);
|
||||
instance = obj;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract fsResult DoSerialize(TModel model, Dictionary<string, fsData> serialized);
|
||||
protected abstract fsResult DoDeserialize(Dictionary<string, fsData> data, ref TModel model);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f7796db4e1a6f0f4b890a0db01cfc258
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,16 +0,0 @@
|
|||
// note: This file contains exceptions used by FullSerializer. Exceptions are never used at runtime
|
||||
// in FullSerializer; they are only used when validating annotations and code-based models.
|
||||
|
||||
using System;
|
||||
|
||||
namespace FullSerializer {
|
||||
public sealed class fsMissingVersionConstructorException : Exception {
|
||||
public fsMissingVersionConstructorException(Type versionedType, Type constructorType) :
|
||||
base(versionedType + " is missing a constructor for previous model type " + constructorType) { }
|
||||
}
|
||||
|
||||
public sealed class fsDuplicateVersionNameException : Exception {
|
||||
public fsDuplicateVersionNameException(Type typeA, Type typeB, string version) :
|
||||
base(typeA + " and " + typeB + " have the same version string (" + version + "); please change one of them.") { }
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3425b211a44d09c48a09b46e76c3146a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,97 +0,0 @@
|
|||
using System;
|
||||
#if !NO_UNITY
|
||||
using UnityEngine;
|
||||
#endif
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WSA
|
||||
// For System.Reflection.TypeExtensions
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// Extend this interface on your type to receive notifications about serialization/deserialization events. If you don't
|
||||
/// have access to the type itself, then you can write an fsObjectProcessor instead.
|
||||
/// </summary>
|
||||
public interface fsISerializationCallbacks {
|
||||
/// <summary>
|
||||
/// Called before serialization.
|
||||
/// </summary>
|
||||
void OnBeforeSerialize(Type storageType);
|
||||
|
||||
/// <summary>
|
||||
/// Called after serialization.
|
||||
/// </summary>
|
||||
/// <param name="storageType">The field/property type that is storing the instance.</param>
|
||||
/// <param name="data">The data that was serialized.</param>
|
||||
void OnAfterSerialize(Type storageType, ref fsData data);
|
||||
|
||||
/// <summary>
|
||||
/// Called before deserialization.
|
||||
/// </summary>
|
||||
/// <param name="storageType">The field/property type that is storing the instance.</param>
|
||||
/// <param name="data">The data that will be used for deserialization.</param>
|
||||
void OnBeforeDeserialize(Type storageType, ref fsData data);
|
||||
|
||||
/// <summary>
|
||||
/// Called after deserialization.
|
||||
/// </summary>
|
||||
/// <param name="storageType">The field/property type that is storing the instance.</param>
|
||||
/// <param name="instance">The type of the instance.</param>
|
||||
void OnAfterDeserialize(Type storageType);
|
||||
}
|
||||
}
|
||||
|
||||
namespace FullSerializer.Internal {
|
||||
public class fsSerializationCallbackProcessor : fsObjectProcessor {
|
||||
public override bool CanProcess(Type type) {
|
||||
return typeof(fsISerializationCallbacks).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override void OnBeforeSerialize(Type storageType, object instance) {
|
||||
// Don't call the callback on null instances.
|
||||
if(instance == null) return;
|
||||
((fsISerializationCallbacks)instance).OnBeforeSerialize(storageType);
|
||||
}
|
||||
|
||||
public override void OnAfterSerialize(Type storageType, object instance, ref fsData data) {
|
||||
// Don't call the callback on null instances.
|
||||
if(instance == null) return;
|
||||
((fsISerializationCallbacks)instance).OnAfterSerialize(storageType, ref data);
|
||||
}
|
||||
|
||||
public override void OnBeforeDeserializeAfterInstanceCreation(Type storageType, object instance, ref fsData data) {
|
||||
if (instance is fsISerializationCallbacks == false) {
|
||||
throw new InvalidCastException("Please ensure the converter for " + storageType + " actually returns an instance of it, not an instance of " + instance.GetType());
|
||||
}
|
||||
|
||||
((fsISerializationCallbacks)instance).OnBeforeDeserialize(storageType, ref data);
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize(Type storageType, object instance) {
|
||||
// Don't call the callback on null instances.
|
||||
if(instance == null) return;
|
||||
((fsISerializationCallbacks)instance).OnAfterDeserialize(storageType);
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_UNITY
|
||||
public class fsSerializationCallbackReceiverProcessor : fsObjectProcessor {
|
||||
public override bool CanProcess(Type type) {
|
||||
return typeof(ISerializationCallbackReceiver).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public override void OnBeforeSerialize(Type storageType, object instance) {
|
||||
// Don't call the callback on null instances.
|
||||
if(instance == null) return;
|
||||
((ISerializationCallbackReceiver)instance).OnBeforeSerialize();
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize(Type storageType, object instance) {
|
||||
// Don't call the callback on null instances.
|
||||
if(instance == null) return;
|
||||
((ISerializationCallbackReceiver)instance).OnAfterDeserialize();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d8d502851fa3a1468d7a69bef2536cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,10 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// The given property or field annotated with [JsonIgnore] will not be serialized.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public sealed class fsIgnoreAttribute : Attribute {
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 52525c31751c2a54d8e3fca6e7c0caa6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,505 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace FullSerializer {
|
||||
// TODO: properly propagate warnings/etc for fsResult states
|
||||
|
||||
/// <summary>
|
||||
/// A simple recursive descent parser for JSON.
|
||||
/// </summary>
|
||||
public class fsJsonParser {
|
||||
private int _start;
|
||||
private string _input;
|
||||
|
||||
private fsResult MakeFailure(string message) {
|
||||
int start = Math.Max(0, _start - 20);
|
||||
int length = Math.Min(50, _input.Length - start);
|
||||
|
||||
string error = "Error while parsing: " + message + "; context = <" +
|
||||
_input.Substring(start, length) + ">";
|
||||
return fsResult.Fail(error);
|
||||
}
|
||||
|
||||
private bool TryMoveNext() {
|
||||
if (_start < _input.Length) {
|
||||
++_start;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasValue() {
|
||||
return HasValue(0);
|
||||
}
|
||||
|
||||
private bool HasValue(int offset) {
|
||||
return (_start + offset) >= 0 && (_start + offset) < _input.Length;
|
||||
}
|
||||
|
||||
private char Character() {
|
||||
return Character(0);
|
||||
}
|
||||
|
||||
private char Character(int offset) {
|
||||
return _input[_start + offset];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skips input such that Character() will return a non-whitespace character
|
||||
/// </summary>
|
||||
private void SkipSpace() {
|
||||
while (HasValue()) {
|
||||
char c = Character();
|
||||
|
||||
// whitespace; fine to skip
|
||||
if (char.IsWhiteSpace(c)) {
|
||||
TryMoveNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
// comment?
|
||||
if (HasValue(1) && Character(0) == '/') {
|
||||
if (Character(1) == '/') {
|
||||
// skip the rest of the line
|
||||
while (HasValue() && Environment.NewLine.Contains("" + Character()) == false) {
|
||||
TryMoveNext();
|
||||
}
|
||||
continue;
|
||||
} else if (Character(1) == '*') {
|
||||
// skip to comment close
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
while (HasValue(1)) {
|
||||
if (Character(0) == '*' && Character(1) == '/') {
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
break;
|
||||
} else {
|
||||
TryMoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
// let other checks to check fail
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#region Escaping
|
||||
private bool IsHex(char c) {
|
||||
return ((c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'f') ||
|
||||
(c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
private uint ParseSingleChar(char c1, uint multipliyer) {
|
||||
uint p1 = 0;
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
p1 = (uint)(c1 - '0') * multipliyer;
|
||||
else if (c1 >= 'A' && c1 <= 'F')
|
||||
p1 = (uint)((c1 - 'A') + 10) * multipliyer;
|
||||
else if (c1 >= 'a' && c1 <= 'f')
|
||||
p1 = (uint)((c1 - 'a') + 10) * multipliyer;
|
||||
return p1;
|
||||
}
|
||||
|
||||
private uint ParseUnicode(char c1, char c2, char c3, char c4) {
|
||||
uint p1 = ParseSingleChar(c1, 0x1000);
|
||||
uint p2 = ParseSingleChar(c2, 0x100);
|
||||
uint p3 = ParseSingleChar(c3, 0x10);
|
||||
uint p4 = ParseSingleChar(c4, 0x1);
|
||||
|
||||
return p1 + p2 + p3 + p4;
|
||||
}
|
||||
|
||||
private fsResult TryUnescapeChar(out char escaped) {
|
||||
// skip leading backslash '\'
|
||||
TryMoveNext();
|
||||
if (HasValue() == false) {
|
||||
escaped = ' ';
|
||||
return MakeFailure("Unexpected end of input after \\");
|
||||
}
|
||||
|
||||
switch (Character()) {
|
||||
case '\\': TryMoveNext(); escaped = '\\'; return fsResult.Success;
|
||||
case '/': TryMoveNext(); escaped = '/'; return fsResult.Success;
|
||||
case '"': TryMoveNext(); escaped = '\"'; return fsResult.Success;
|
||||
case 'a': TryMoveNext(); escaped = '\a'; return fsResult.Success;
|
||||
case 'b': TryMoveNext(); escaped = '\b'; return fsResult.Success;
|
||||
case 'f': TryMoveNext(); escaped = '\f'; return fsResult.Success;
|
||||
case 'n': TryMoveNext(); escaped = '\n'; return fsResult.Success;
|
||||
case 'r': TryMoveNext(); escaped = '\r'; return fsResult.Success;
|
||||
case 't': TryMoveNext(); escaped = '\t'; return fsResult.Success;
|
||||
case '0': TryMoveNext(); escaped = '\0'; return fsResult.Success;
|
||||
case 'u':
|
||||
TryMoveNext();
|
||||
if (IsHex(Character(0))
|
||||
&& IsHex(Character(1))
|
||||
&& IsHex(Character(2))
|
||||
&& IsHex(Character(3))) {
|
||||
|
||||
uint codePoint = ParseUnicode(Character(0), Character(1), Character(2), Character(3));
|
||||
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
TryMoveNext();
|
||||
|
||||
escaped = (char)codePoint;
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
// invalid escape sequence
|
||||
escaped = (char)0;
|
||||
return MakeFailure(
|
||||
string.Format("invalid escape sequence '\\u{0}{1}{2}{3}'\n",
|
||||
Character(0),
|
||||
Character(1),
|
||||
Character(2),
|
||||
Character(3)));
|
||||
default:
|
||||
escaped = (char)0;
|
||||
return MakeFailure(string.Format("Invalid escape sequence \\{0}", Character()));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private fsResult TryParseExact(string content) {
|
||||
for (int i = 0; i < content.Length; ++i) {
|
||||
if (Character() != content[i]) {
|
||||
return MakeFailure("Expected " + content[i]);
|
||||
}
|
||||
|
||||
if (TryMoveNext() == false) {
|
||||
return MakeFailure("Unexpected end of content when parsing " + content);
|
||||
}
|
||||
}
|
||||
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
private fsResult TryParseTrue(out fsData data) {
|
||||
var fail = TryParseExact("true");
|
||||
|
||||
if (fail.Succeeded) {
|
||||
data = new fsData(true);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
data = null;
|
||||
return fail;
|
||||
}
|
||||
|
||||
private fsResult TryParseFalse(out fsData data) {
|
||||
var fail = TryParseExact("false");
|
||||
|
||||
if (fail.Succeeded) {
|
||||
data = new fsData(false);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
data = null;
|
||||
return fail;
|
||||
}
|
||||
|
||||
private fsResult TryParseNull(out fsData data) {
|
||||
var fail = TryParseExact("null");
|
||||
|
||||
if (fail.Succeeded) {
|
||||
data = new fsData();
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
data = null;
|
||||
return fail;
|
||||
}
|
||||
|
||||
|
||||
private bool IsSeparator(char c) {
|
||||
return char.IsWhiteSpace(c) || c == ',' || c == '}' || c == ']';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses numbers that follow the regular expression [-+](\d+|\d*\.\d*)
|
||||
/// </summary>
|
||||
private fsResult TryParseNumber(out fsData data) {
|
||||
int start = _start;
|
||||
|
||||
// read until we get to a separator
|
||||
while (
|
||||
TryMoveNext() &&
|
||||
(HasValue() && IsSeparator(Character()) == false)) {
|
||||
}
|
||||
|
||||
// try to parse the value
|
||||
string numberString = _input.Substring(start, _start - start);
|
||||
|
||||
// double -- includes a .
|
||||
if (numberString.Contains(".") || numberString.Contains("e") || numberString.Contains("E") ||
|
||||
numberString == "Infinity" || numberString == "-Infinity" || numberString == "NaN") {
|
||||
double doubleValue;
|
||||
if (double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue) == false) {
|
||||
data = null;
|
||||
return MakeFailure("Bad double format with " + numberString);
|
||||
}
|
||||
|
||||
data = new fsData(doubleValue);
|
||||
return fsResult.Success;
|
||||
}
|
||||
else {
|
||||
Int64 intValue;
|
||||
if (Int64.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out intValue) == false) {
|
||||
data = null;
|
||||
return MakeFailure("Bad Int64 format with " + numberString);
|
||||
}
|
||||
|
||||
data = new fsData(intValue);
|
||||
return fsResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly StringBuilder _cachedStringBuilder = new StringBuilder(256);
|
||||
/// <summary>
|
||||
/// Parses a string
|
||||
/// </summary>
|
||||
private fsResult TryParseString(out string str) {
|
||||
_cachedStringBuilder.Length = 0;
|
||||
|
||||
// skip the first "
|
||||
if (Character() != '"' || TryMoveNext() == false) {
|
||||
str = string.Empty;
|
||||
return MakeFailure("Expected initial \" when parsing a string");
|
||||
}
|
||||
|
||||
// read until the next "
|
||||
while (HasValue() && Character() != '\"') {
|
||||
char c = Character();
|
||||
|
||||
// escape if necessary
|
||||
if (c == '\\') {
|
||||
char unescaped;
|
||||
var fail = TryUnescapeChar(out unescaped);
|
||||
if (fail.Failed) {
|
||||
str = string.Empty;
|
||||
return fail;
|
||||
}
|
||||
|
||||
_cachedStringBuilder.Append(unescaped);
|
||||
}
|
||||
|
||||
// no escaping necessary
|
||||
else {
|
||||
_cachedStringBuilder.Append(c);
|
||||
|
||||
// get the next character
|
||||
if (TryMoveNext() == false) {
|
||||
str = string.Empty;
|
||||
return MakeFailure("Unexpected end of input when reading a string");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// skip the first "
|
||||
if (HasValue() == false || Character() != '"' || TryMoveNext() == false) {
|
||||
str = string.Empty;
|
||||
return MakeFailure("No closing \" when parsing a string");
|
||||
}
|
||||
|
||||
str = _cachedStringBuilder.ToString();
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses an array
|
||||
/// </summary>
|
||||
private fsResult TryParseArray(out fsData arr) {
|
||||
if (Character() != '[') {
|
||||
arr = null;
|
||||
return MakeFailure("Expected initial [ when parsing an array");
|
||||
}
|
||||
|
||||
// skip '['
|
||||
if (TryMoveNext() == false) {
|
||||
arr = null;
|
||||
return MakeFailure("Unexpected end of input when parsing an array");
|
||||
}
|
||||
SkipSpace();
|
||||
|
||||
var result = new List<fsData>();
|
||||
|
||||
while (HasValue() && Character() != ']') {
|
||||
// parse the element
|
||||
fsData element;
|
||||
var fail = RunParse(out element);
|
||||
if (fail.Failed) {
|
||||
arr = null;
|
||||
return fail;
|
||||
}
|
||||
|
||||
result.Add(element);
|
||||
|
||||
// parse the comma
|
||||
SkipSpace();
|
||||
if (HasValue() && Character() == ',') {
|
||||
if (TryMoveNext() == false) break;
|
||||
SkipSpace();
|
||||
}
|
||||
}
|
||||
|
||||
// skip the final ]
|
||||
if (HasValue() == false || Character() != ']' || TryMoveNext() == false) {
|
||||
arr = null;
|
||||
return MakeFailure("No closing ] for array");
|
||||
}
|
||||
|
||||
arr = new fsData(result);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
private fsResult TryParseObject(out fsData obj) {
|
||||
if (Character() != '{') {
|
||||
obj = null;
|
||||
return MakeFailure("Expected initial { when parsing an object");
|
||||
}
|
||||
|
||||
// skip '{'
|
||||
if (TryMoveNext() == false) {
|
||||
obj = null;
|
||||
return MakeFailure("Unexpected end of input when parsing an object");
|
||||
}
|
||||
SkipSpace();
|
||||
|
||||
var result = new Dictionary<string, fsData>(
|
||||
fsGlobalConfig.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
while (HasValue() && Character() != '}') {
|
||||
fsResult failure;
|
||||
|
||||
// parse the key
|
||||
SkipSpace();
|
||||
string key;
|
||||
failure = TryParseString(out key);
|
||||
if (failure.Failed) {
|
||||
obj = null;
|
||||
return failure;
|
||||
}
|
||||
SkipSpace();
|
||||
|
||||
// parse the ':' after the key
|
||||
if (HasValue() == false || Character() != ':' || TryMoveNext() == false) {
|
||||
obj = null;
|
||||
return MakeFailure("Expected : after key \"" + key + "\"");
|
||||
}
|
||||
SkipSpace();
|
||||
|
||||
// parse the value
|
||||
fsData value;
|
||||
failure = RunParse(out value);
|
||||
if (failure.Failed) {
|
||||
obj = null;
|
||||
return failure;
|
||||
}
|
||||
|
||||
result.Add(key, value);
|
||||
|
||||
// parse the comma
|
||||
SkipSpace();
|
||||
if (HasValue() && Character() == ',') {
|
||||
if (TryMoveNext() == false) break;
|
||||
SkipSpace();
|
||||
}
|
||||
}
|
||||
|
||||
// skip the final }
|
||||
if (HasValue() == false || Character() != '}' || TryMoveNext() == false) {
|
||||
obj = null;
|
||||
return MakeFailure("No closing } for object");
|
||||
}
|
||||
|
||||
obj = new fsData(result);
|
||||
return fsResult.Success;
|
||||
}
|
||||
|
||||
private fsResult RunParse(out fsData data) {
|
||||
SkipSpace();
|
||||
|
||||
if (HasValue() == false) {
|
||||
data = default(fsData);
|
||||
return MakeFailure("Unexpected end of input");
|
||||
}
|
||||
|
||||
switch (Character()) {
|
||||
case 'I': // Infinity
|
||||
case 'N': // NaN
|
||||
case '.':
|
||||
case '+':
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': return TryParseNumber(out data);
|
||||
case '"': {
|
||||
string str;
|
||||
fsResult fail = TryParseString(out str);
|
||||
if (fail.Failed) {
|
||||
data = null;
|
||||
return fail;
|
||||
}
|
||||
data = new fsData(str);
|
||||
return fsResult.Success;
|
||||
}
|
||||
case '[': return TryParseArray(out data);
|
||||
case '{': return TryParseObject(out data);
|
||||
case 't': return TryParseTrue(out data);
|
||||
case 'f': return TryParseFalse(out data);
|
||||
case 'n': return TryParseNull(out data);
|
||||
default:
|
||||
data = null;
|
||||
return MakeFailure("unable to parse; invalid token \"" + Character() + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the specified input. Returns a failure state if parsing failed.
|
||||
/// </summary>
|
||||
/// <param name="input">The input to parse.</param>
|
||||
/// <param name="data">The parsed data. This is undefined if parsing fails.</param>
|
||||
/// <returns>The parsed input.</returns>
|
||||
public static fsResult Parse(string input, out fsData data) {
|
||||
if (string.IsNullOrEmpty(input)) {
|
||||
data = default(fsData);
|
||||
return fsResult.Fail("No input");
|
||||
}
|
||||
|
||||
var context = new fsJsonParser(input);
|
||||
return context.RunParse(out data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Parse that does not allow the error information
|
||||
/// to be recovered.
|
||||
/// </summary>
|
||||
public static fsData Parse(string input) {
|
||||
fsData data;
|
||||
Parse(input, out data).AssertSuccess();
|
||||
return data;
|
||||
}
|
||||
|
||||
private fsJsonParser(string input) {
|
||||
_input = input;
|
||||
_start = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4c3e5a8da8796c84798679d00813622a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,287 +0,0 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FullSerializer {
|
||||
public static class fsJsonPrinter {
|
||||
/// <summary>
|
||||
/// Inserts the given number of indents into the builder.
|
||||
/// </summary>
|
||||
private static void InsertSpacing(TextWriter stream, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
stream.Write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escapes a string.
|
||||
/// </summary>
|
||||
private static string EscapeString(string str) {
|
||||
// Escaping a string is pretty allocation heavy, so we try hard to not do it.
|
||||
|
||||
bool needsEscape = false;
|
||||
for (int i = 0; i < str.Length; ++i) {
|
||||
char c = str[i];
|
||||
|
||||
// unicode code point
|
||||
int intChar = Convert.ToInt32(c);
|
||||
if (intChar < 0 || intChar > 127) {
|
||||
needsEscape = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// standard escape character
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '\a':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\0':
|
||||
needsEscape = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsEscape) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsEscape == false) {
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < str.Length; ++i) {
|
||||
char c = str[i];
|
||||
|
||||
// unicode code point
|
||||
int intChar = Convert.ToInt32(c);
|
||||
if (intChar < 0 || intChar > 127) {
|
||||
result.Append(string.Format("\\u{0:x4} ", intChar).Trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
// standard escape character
|
||||
switch (c) {
|
||||
case '"': result.Append("\\\""); continue;
|
||||
case '\\': result.Append(@"\\"); continue;
|
||||
case '\a': result.Append(@"\a"); continue;
|
||||
case '\b': result.Append(@"\b"); continue;
|
||||
case '\f': result.Append(@"\f"); continue;
|
||||
case '\n': result.Append(@"\n"); continue;
|
||||
case '\r': result.Append(@"\r"); continue;
|
||||
case '\t': result.Append(@"\t"); continue;
|
||||
case '\0': result.Append(@"\0"); continue;
|
||||
}
|
||||
|
||||
// no escaping needed
|
||||
result.Append(c);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static void BuildCompressedString(fsData data, TextWriter stream) {
|
||||
switch (data.Type) {
|
||||
case fsDataType.Null:
|
||||
stream.Write("null");
|
||||
break;
|
||||
|
||||
case fsDataType.Boolean:
|
||||
if (data.AsBool) stream.Write("true");
|
||||
else stream.Write("false");
|
||||
break;
|
||||
|
||||
case fsDataType.Double:
|
||||
// doubles must *always* include a decimal
|
||||
stream.Write(ConvertDoubleToString(data.AsDouble));
|
||||
break;
|
||||
|
||||
case fsDataType.Int64:
|
||||
stream.Write(data.AsInt64);
|
||||
break;
|
||||
|
||||
case fsDataType.String:
|
||||
stream.Write('"');
|
||||
stream.Write(EscapeString(data.AsString));
|
||||
stream.Write('"');
|
||||
break;
|
||||
|
||||
case fsDataType.Object: {
|
||||
stream.Write('{');
|
||||
bool comma = false;
|
||||
foreach (var entry in data.AsDictionary) {
|
||||
if (comma) stream.Write(',');
|
||||
comma = true;
|
||||
stream.Write('"');
|
||||
stream.Write(entry.Key);
|
||||
stream.Write('"');
|
||||
stream.Write(":");
|
||||
BuildCompressedString(entry.Value, stream);
|
||||
}
|
||||
stream.Write('}');
|
||||
break;
|
||||
}
|
||||
|
||||
case fsDataType.Array: {
|
||||
stream.Write('[');
|
||||
bool comma = false;
|
||||
foreach (var entry in data.AsList) {
|
||||
if (comma) stream.Write(',');
|
||||
comma = true;
|
||||
BuildCompressedString(entry, stream);
|
||||
}
|
||||
stream.Write(']');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats this data into the given builder.
|
||||
/// </summary>
|
||||
private static void BuildPrettyString(fsData data, TextWriter stream, int depth) {
|
||||
switch (data.Type) {
|
||||
case fsDataType.Null:
|
||||
stream.Write("null");
|
||||
break;
|
||||
|
||||
case fsDataType.Boolean:
|
||||
if (data.AsBool) stream.Write("true");
|
||||
else stream.Write("false");
|
||||
break;
|
||||
|
||||
case fsDataType.Double:
|
||||
stream.Write(ConvertDoubleToString(data.AsDouble));
|
||||
break;
|
||||
|
||||
case fsDataType.Int64:
|
||||
stream.Write(data.AsInt64);
|
||||
break;
|
||||
|
||||
|
||||
case fsDataType.String:
|
||||
stream.Write('"');
|
||||
stream.Write(EscapeString(data.AsString));
|
||||
stream.Write('"');
|
||||
break;
|
||||
|
||||
case fsDataType.Object: {
|
||||
stream.Write('{');
|
||||
stream.WriteLine();
|
||||
bool comma = false;
|
||||
foreach (var entry in data.AsDictionary) {
|
||||
if (comma) {
|
||||
stream.Write(',');
|
||||
stream.WriteLine();
|
||||
}
|
||||
comma = true;
|
||||
InsertSpacing(stream, depth + 1);
|
||||
stream.Write('"');
|
||||
stream.Write(entry.Key);
|
||||
stream.Write('"');
|
||||
stream.Write(": ");
|
||||
BuildPrettyString(entry.Value, stream, depth + 1);
|
||||
}
|
||||
stream.WriteLine();
|
||||
InsertSpacing(stream, depth);
|
||||
stream.Write('}');
|
||||
break;
|
||||
}
|
||||
|
||||
case fsDataType.Array:
|
||||
// special case for empty lists; we don't put an empty line between the brackets
|
||||
if (data.AsList.Count == 0) {
|
||||
stream.Write("[]");
|
||||
}
|
||||
|
||||
else {
|
||||
bool comma = false;
|
||||
|
||||
stream.Write('[');
|
||||
stream.WriteLine();
|
||||
foreach (var entry in data.AsList) {
|
||||
if (comma) {
|
||||
stream.Write(',');
|
||||
stream.WriteLine();
|
||||
}
|
||||
comma = true;
|
||||
InsertSpacing(stream, depth + 1);
|
||||
BuildPrettyString(entry, stream, depth + 1);
|
||||
}
|
||||
stream.WriteLine();
|
||||
InsertSpacing(stream, depth);
|
||||
stream.Write(']');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the pretty JSON output data to the given stream.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to print.</param>
|
||||
/// <param name="outputStream">Where to write the printed data.</param>
|
||||
public static void PrettyJson(fsData data, TextWriter outputStream) {
|
||||
BuildPrettyString(data, outputStream, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the data in a pretty printed JSON format.
|
||||
/// </summary>
|
||||
public static string PrettyJson(fsData data) {
|
||||
var sb = new StringBuilder();
|
||||
using (var writer = new StringWriter(sb)) {
|
||||
BuildPrettyString(data, writer, 0);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the compressed JSON output data to the given stream.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to print.</param>
|
||||
/// <param name="outputStream">Where to write the printed data.</param>
|
||||
public static void CompressedJson(fsData data, StreamWriter outputStream) {
|
||||
BuildCompressedString(data, outputStream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the data in a relatively compressed JSON format.
|
||||
/// </summary>
|
||||
public static string CompressedJson(fsData data) {
|
||||
var sb = new StringBuilder();
|
||||
using (var writer = new StringWriter(sb)) {
|
||||
BuildCompressedString(data, writer);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility method that converts a double to a string.
|
||||
/// </summary>
|
||||
private static string ConvertDoubleToString(double d) {
|
||||
if (Double.IsInfinity(d) || Double.IsNaN(d))
|
||||
return d.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
string doubledString = d.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
// NOTE/HACK: If we don't serialize with a period or an exponent,
|
||||
// then the number will be deserialized as an Int64, not a double.
|
||||
if (doubledString.Contains(".") == false &&
|
||||
doubledString.Contains("e") == false &&
|
||||
doubledString.Contains("E") == false) {
|
||||
doubledString += ".0";
|
||||
}
|
||||
|
||||
return doubledString;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4e795bc949226ef4d8a63c2f4bd3bdf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,21 +0,0 @@
|
|||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// Controls how the reflected converter handles member serialization.
|
||||
/// </summary>
|
||||
public enum fsMemberSerialization {
|
||||
/// <summary>
|
||||
/// Only members with [SerializeField] or [fsProperty] attributes are serialized.
|
||||
/// </summary>
|
||||
OptIn,
|
||||
|
||||
/// <summary>
|
||||
/// Only members with [NotSerialized] or [fsIgnore] will not be serialized.
|
||||
/// </summary>
|
||||
OptOut,
|
||||
|
||||
/// <summary>
|
||||
/// The default member serialization behavior is applied.
|
||||
/// </summary>
|
||||
Default
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3191f05f033e23947b48c7694d12e76c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,52 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace FullSerializer {
|
||||
/// <summary>
|
||||
/// This attribute controls some serialization behavior for a type. See the comments
|
||||
/// on each of the fields for more information.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
||||
public sealed class fsObjectAttribute : Attribute {
|
||||
/// <summary>
|
||||
/// The previous model that should be used if an old version of this
|
||||
/// object is encountered. Using this attribute also requires that the
|
||||
/// type have a public constructor that takes only one parameter, an object
|
||||
/// instance of the given type. Use of this parameter *requires* that
|
||||
/// the VersionString parameter is also set.
|
||||
/// </summary>
|
||||
public Type[] PreviousModels;
|
||||
|
||||
/// <summary>
|
||||
/// The version string to use for this model. This should be unique among all
|
||||
/// prior versions of this model that is supported for importation. If PreviousModel
|
||||
/// is set, then this attribute must also be set. A good valid example for this
|
||||
/// is "v1", "v2", "v3", ...
|
||||
/// </summary>
|
||||
public string VersionString;
|
||||
|
||||
/// <summary>
|
||||
/// This controls the behavior for member serialization.
|
||||
/// The default behavior is fsMemberSerialization.Default.
|
||||
/// </summary>
|
||||
public fsMemberSerialization MemberSerialization = fsMemberSerialization.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Specify a custom converter to use for serialization. The converter type needs
|
||||
/// to derive from fsBaseConverter. This defaults to null.
|
||||
/// </summary>
|
||||
public Type Converter;
|
||||
|
||||
/// <summary>
|
||||
/// Specify a custom processor to use during serialization. The processor type needs
|
||||
/// to derive from fsObjectProcessor and the call to CanProcess is not invoked. This
|
||||
/// defaults to null.
|
||||
/// </summary>
|
||||
public Type Processor;
|
||||
|
||||
public fsObjectAttribute() { }
|
||||
public fsObjectAttribute(string versionString, params Type[] previousModels) {
|
||||
VersionString = versionString;
|
||||
PreviousModels = previousModels;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ccb6d168f2ca6b34da57030c4d6edfcd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue