implement deserializer generator

This commit is contained in:
ousttrue
2019-08-08 20:25:37 +09:00
parent 9cddcc4784
commit ce2c2d2892
16 changed files with 3497 additions and 159 deletions

View File

@@ -0,0 +1,115 @@
using System;
using System.IO;
namespace UniGLTF
{
public class ArraySerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public ArraySerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_ARRAY";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new $1[parsed.GetArrayCount()];
int i=0;
foreach(var x in parsed.ArrayItems())
{
value[i++] = $3;
}
return value;
}
"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "x"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
public class ListSerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public ListSerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_LIST";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new List<$1>();
foreach(var x in parsed.ArrayItems())
{
value.Add($3);
}
return value;
}"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "x"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
public class StringKeyDictionarySerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public StringKeyDictionarySerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_DICT";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new Dictionary<string, $1>();
foreach(var kv in parsed.ObjectItems())
{
value.Add(kv.Key.GetString(), $3);
}
return value;
}
"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "kv.Value"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e85f0c5204f5ac3429503462ef29cdae
timeCreated: 1565259169
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,178 +1,61 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Text;
using UniJSON;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public class FieldSerializationInfo
{
FieldInfo m_fi;
string m_path;
JsonSchemaAttribute m_attr;
ObjectSerializationInfo m_child;
public FieldSerializationInfo(FieldInfo fi, string path)
{
m_fi = fi;
m_path = path;
m_attr = fi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(JsonSchemaAttribute)) as JsonSchemaAttribute;
var suffix = default(string);
var t = default(Type);
var isDictionary = default(bool);
GetCollectionType(fi.FieldType, out suffix, out t, out isDictionary);
if (t == typeof(object))
{
// 終わり
return;
}
if (fi.IsLiteral && !fi.IsInitOnly)
{
// const
// 終わり
return;
}
if (t.IsClass && t.GetFields(DeserializerGenerator.FIELD_FLAGS).Length == 0)
{
// 終わり
return;
}
if (IsPrimitive(t))
{
// 終わり
return;
}
m_child = new ObjectSerializationInfo(t, m_path + "/" + m_fi.Name + suffix);
}
static void GetCollectionType(Type t, out string suffix, out Type collectionType, out bool isDictionary)
{
if (t.IsArray)
{
suffix = "[]";
collectionType = t.GetElementType();
isDictionary = false;
return;
}
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>))
{
suffix = "[]";
collectionType = t.GetGenericArguments()[0];
isDictionary = false;
return;
}
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>)
&& t.GetGenericArguments()[0] == typeof(string))
{
suffix = "";
collectionType = t.GetGenericArguments()[1];
isDictionary = true;
return;
}
suffix = "";
collectionType = t;
isDictionary = false;
}
static bool IsPrimitive(Type t)
{
if (t == typeof(sbyte)
|| t == typeof(short)
|| t == typeof(int)
|| t == typeof(long)
|| t == typeof(byte)
|| t == typeof(ushort)
|| t == typeof(uint)
|| t == typeof(ulong)
|| t == typeof(float)
|| t == typeof(double)
|| t == typeof(string)
|| t == typeof(bool)
)
{
return true;
}
if (t.IsEnum)
{
return true;
}
return false;
}
public override string ToString()
{
var sb = new StringBuilder();
var typeName = BaseJsonSchemaAttribute.GetTypeName(m_fi.FieldType);
if (m_attr != null)
{
sb.AppendLine(string.Format("{0}/{1}: {2}", m_path, m_fi.Name, m_attr.GetInfo(m_fi)));
}
else
{
sb.AppendLine(string.Format("{0}/{1}: {2}", m_path, m_fi.Name, typeName));
}
if (m_child != null)
{
sb.Append(m_child.ToString());
}
return sb.ToString();
}
}
public class ObjectSerializationInfo
{
string m_path;
FieldSerializationInfo[] m_fsi;
public ObjectSerializationInfo(Type t, string path)
{
m_path = path;
m_fsi = t.GetFields(DeserializerGenerator.FIELD_FLAGS).Select(x =>
{
return new FieldSerializationInfo(x, path);
}).ToArray();
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var x in m_fsi)
{
sb.Append(x.ToString());
}
return sb.ToString();
}
}
public static class DeserializerGenerator
{
public const BindingFlags FIELD_FLAGS = BindingFlags.Instance | BindingFlags.Public;
static string OutPath
{
get
{
return Path.Combine(UnityEngine.Application.dataPath,
"VRM/UniGLTF/Scripts/IO/GltfDeserializer.g.cs");
}
}
/// <summary>
/// AOT向けにデシリアライザを生成する
/// </summary>
[MenuItem(VRM.VRMVersion.MENU + "/Generate Deserializer")]
static void GenerateSerializer()
{
var info = new ObjectSerializationInfo(typeof(glTF), "gltf");
var info = new ObjectSerialization(typeof(glTF), "gltf");
Debug.Log(info);
using (var s = File.Open(OutPath, FileMode.Create))
using (var w = new StreamWriter(s, Encoding.UTF8))
{
// header
w.Write(@"
using UniJSON;
using System;
using System.Collections.Generic;
using VRM;
using UnityEngine;
namespace UniGLTF {
public static class GltfDeserializer
{
");
info.GenerateDeserializer(w, "Deserialize");
// footer
w.Write(@"
} // GltfDeserializer
} // UniGLTF
");
Debug.LogFormat("write: {0}", OutPath);
}
}
}
}

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UniJSON;
namespace UniGLTF
{
public class FieldSerializationInfo
{
FieldInfo m_fi;
public FieldInfo FieldInfo
{
get { return m_fi; }
}
public string Name
{
get { return FieldInfo.Name; }
}
public string Path
{
get;
private set;
}
public string FunctionName
{
get
{
return "Deserialize_" + Path
.Replace("/", "_")
.Replace("[]", "_")
;
}
}
JsonSchemaAttribute m_attr;
public IValueSerialization Serialization
{
get;
private set;
}
public FieldSerializationInfo(FieldInfo fi, string path)
{
m_fi = fi;
Path = path + "/" + fi.Name;
m_attr = fi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(JsonSchemaAttribute)) as JsonSchemaAttribute;
Serialization = GetSerialization(m_fi.FieldType, Path);
}
static IValueSerialization GetSerialization(Type t, string path)
{
if (t.IsArray)
{
return new ArraySerialization(t,
GetSerialization(t.GetElementType(), path + "[]"));
}
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>))
{
return new ListSerialization(t,
GetSerialization(t.GetGenericArguments()[0], path + "[]"));
}
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>)
&& t.GetGenericArguments()[0] == typeof(string))
{
return new StringKeyDictionarySerialization(t,
GetSerialization(t.GetGenericArguments()[1], path));
}
// GetCollectionType(fi.FieldType, out suffix, out t);
if (t == typeof(sbyte))
{
return new Int8Serialization();
}
else if (t == typeof(short))
{
return new Int16Serialization();
}
else if (t == typeof(int))
{
return new Int32Serialization();
}
else if (t == typeof(long))
{
return new Int64Serialization();
}
else if (t == typeof(byte))
{
return new UInt8Serialization();
}
else if (t == typeof(ushort))
{
return new UInt16Serialization();
}
else if (t == typeof(uint))
{
return new UInt32Serialization();
}
else if (t == typeof(ulong))
{
return new UInt64Serialization();
}
else if (t == typeof(float))
{
return new SingleSerialization();
}
else if (t == typeof(double))
{
return new DoubleSerialization();
}
else if (t == typeof(string))
{
return new StringSerialization();
}
else if (t == typeof(bool))
{
return new BooleanSerialization();
}
else if (t.IsEnum)
{
return new EnumIntSerialization(t);
}
return new ObjectSerialization(t, path);
}
public override string ToString()
{
var sb = new StringBuilder();
var typeName = BaseJsonSchemaAttribute.GetTypeName(m_fi.FieldType);
if (m_attr != null)
{
sb.AppendLine(string.Format("{0}: {1}", Path, m_attr.GetInfo(m_fi)));
}
else
{
sb.AppendLine(string.Format("{0}: {1}", Path, typeName));
}
sb.Append(Serialization.ToString());
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3c26deb26a3941642a30691d374199da
timeCreated: 1565256318
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
using System.IO;
namespace UniGLTF
{
// Use this for initialization
public interface IValueSerialization
{
Type ValueType { get; }
bool IsInline { get; }
string GenerateDeserializerCall(string callName, string argName);
void GenerateDeserializer(StreamWriter writer, string callName);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 199c91bbade4ea043928e29946a28502
timeCreated: 1565256001
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,112 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace UniGLTF
{
public abstract class FunctionSerializationBase : IValueSerialization
{
public Type ValueType
{
get;
protected set;
}
public bool IsInline
{
get { return false; }
}
public abstract void GenerateDeserializer(StreamWriter writer, string callName);
public string GenerateDeserializerCall(string callName, string argName)
{
return string.Format("{0}({1})", callName, argName);
}
}
public class ObjectSerialization : FunctionSerializationBase
{
string m_path;
FieldSerializationInfo[] m_fsi;
public ObjectSerialization(Type t, string path)
{
ValueType = t;
m_path = path;
m_fsi = t.GetFields(DeserializerGenerator.FIELD_FLAGS)
.Where(x =>
{
if (x.FieldType == typeof(object))
{
// object. coannot serialize
return false;
}
if (x.IsLiteral && !x.IsInitOnly)
{
// const
return false;
}
return true;
})
.Select(x =>
{
return new FieldSerializationInfo(x, path);
}).ToArray();
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var x in m_fsi)
{
sb.Append(x.ToString());
}
return sb.ToString();
}
public override void GenerateDeserializer(StreamWriter writer, string parentName)
{
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new $0();
foreach(var kv in parsed.ObjectItems())
{
var key = kv.Key.GetString();
"
.Replace("$0", ValueType.Name)
.Replace("$2", parentName)
);
foreach (var f in m_fsi)
{
writer.Write(@"
if(key==""$0""){
value.$0 = $1;
continue;
}
"
.Replace("$0", f.Name)
.Replace("$1", f.Serialization.GenerateDeserializerCall(f.FunctionName, "kv.Value"))
);
}
writer.Write(@"
}
return value;
}
");
foreach (var f in m_fsi)
{
if (!f.Serialization.IsInline)
{
f.Serialization.GenerateDeserializer(writer, f.FunctionName);
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 87a20b1fb7336e34bbc61c9d7476c6db
timeCreated: 1565256016
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,198 @@
using System;
using System.IO;
namespace UniGLTF
{
public abstract class PrimitiveSerializationBase : IValueSerialization
{
public bool IsInline
{
get { return true; }
}
public abstract Type ValueType { get; }
public void GenerateDeserializer(StreamWriter writer, string callName)
{
throw new System.NotImplementedException();
}
public abstract string GenerateDeserializerCall(string callName, string argName);
}
public class Int8Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(SByte); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt8()";
}
}
public class Int16Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int16); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt16()";
}
}
public class Int32Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int32); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt32()";
}
}
public class Int64Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int64); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt64()";
}
}
public class UInt8Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Byte); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt8()";
}
}
public class UInt16Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt16); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt16()";
}
}
public class UInt32Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt32); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt32()";
}
}
public class UInt64Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt64); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt64()";
}
}
public class SingleSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Single); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetSingle()";
}
}
public class DoubleSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Double); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetDouble()";
}
}
public class BooleanSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Boolean); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetBoolean()";
}
}
public class StringSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(String); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetString()";
}
}
public class EnumIntSerialization : PrimitiveSerializationBase
{
Type m_type;
public override Type ValueType
{
get { return m_type; }
}
public EnumIntSerialization(Type t)
{
m_type = t;
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return string.Format("({0}){1}.GetInt32()", m_type.Name, argName);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8ddae9fc19efaec43a6d3aacad1c8d56
timeCreated: 1565256889
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fd51f973e67cbb448bab93da7ea596a8
timeCreated: 1565245501
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -119,7 +119,7 @@ namespace UniJSON
}
else if (t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
return "Dict<" + string.Join(", ", t.GetGenericArguments().Select(x => x.Name).ToArray()) + ">";
return "Dictionary<" + string.Join(", ", t.GetGenericArguments().Select(x => x.Name).ToArray()) + ">";
}
}

View File

@@ -35,6 +35,7 @@ GraphicsSettings:
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
type: 0}

View File

@@ -70,6 +70,8 @@ PlayerSettings:
captureSingleScreen: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
deferSystemGesturesMode: 0
hideHomeButton: 0
submitAnalytics: 1
usePlayerLog: 1
bakeCollisionMeshes: 0
@@ -99,6 +101,8 @@ PlayerSettings:
n3dsEnableVSync: 0
ignoreAlphaClear: 0
xboxOneResolution: 0
xboxOneSResolution: 0
xboxOneXResolution: 3
xboxOneMonoLoggingLevel: 0
xboxOneLoggingLevel: 1
videoMemoryForVertexBuffers: 0
@@ -172,15 +176,21 @@ PlayerSettings:
iPhone47inSplashScreen: {fileID: 0}
iPhone55inPortraitSplashScreen: {fileID: 0}
iPhone55inLandscapeSplashScreen: {fileID: 0}
iPhone58inPortraitSplashScreen: {fileID: 0}
iPhone58inLandscapeSplashScreen: {fileID: 0}
iPadPortraitSplashScreen: {fileID: 0}
iPadHighResPortraitSplashScreen: {fileID: 0}
iPadLandscapeSplashScreen: {fileID: 0}
iPadHighResLandscapeSplashScreen: {fileID: 0}
appleTVSplashScreen: {fileID: 0}
appleTVSplashScreen2x: {fileID: 0}
tvOSSmallIconLayers: []
tvOSSmallIconLayers2x: []
tvOSLargeIconLayers: []
tvOSTopShelfImageLayers: []
tvOSTopShelfImageLayers2x: []
tvOSTopShelfImageWideLayers: []
tvOSTopShelfImageWideLayers2x: []
iOSLaunchScreenType: 0
iOSLaunchScreenPortrait: {fileID: 0}
iOSLaunchScreenLandscape: {fileID: 0}
@@ -277,6 +287,9 @@ PlayerSettings:
switchTitleNames_9:
switchTitleNames_10:
switchTitleNames_11:
switchTitleNames_12:
switchTitleNames_13:
switchTitleNames_14:
switchPublisherNames_0:
switchPublisherNames_1:
switchPublisherNames_2:
@@ -289,6 +302,9 @@ PlayerSettings:
switchPublisherNames_9:
switchPublisherNames_10:
switchPublisherNames_11:
switchPublisherNames_12:
switchPublisherNames_13:
switchPublisherNames_14:
switchIcons_0: {fileID: 0}
switchIcons_1: {fileID: 0}
switchIcons_2: {fileID: 0}
@@ -301,6 +317,9 @@ PlayerSettings:
switchIcons_9: {fileID: 0}
switchIcons_10: {fileID: 0}
switchIcons_11: {fileID: 0}
switchIcons_12: {fileID: 0}
switchIcons_13: {fileID: 0}
switchIcons_14: {fileID: 0}
switchSmallIcons_0: {fileID: 0}
switchSmallIcons_1: {fileID: 0}
switchSmallIcons_2: {fileID: 0}
@@ -313,6 +332,9 @@ PlayerSettings:
switchSmallIcons_9: {fileID: 0}
switchSmallIcons_10: {fileID: 0}
switchSmallIcons_11: {fileID: 0}
switchSmallIcons_12: {fileID: 0}
switchSmallIcons_13: {fileID: 0}
switchSmallIcons_14: {fileID: 0}
switchManualHTML:
switchAccessibleURLs:
switchLegalInformation:
@@ -354,6 +376,7 @@ PlayerSettings:
switchLocalCommunicationIds_7:
switchParentalControl: 0
switchAllowsScreenshot: 1
switchAllowsVideoCapturing: 1
switchDataLossConfirmation: 0
switchSupportedNpadStyles: 3
switchSocketConfigEnabled: 0
@@ -496,7 +519,8 @@ PlayerSettings:
webGLUseEmbeddedResources: 0
webGLUseWasm: 0
webGLCompressionFormat: 1
scriptingDefineSymbols: {}
scriptingDefineSymbols:
1: VRM_DEVELOP
platformArchitecture: {}
scriptingBackend: {}
incrementalIl2cppBuild: {}