SchemaTypes.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace SharpGLTF.SchemaReflection
  7. {
  8. /// <summary>
  9. /// Base class for all schema Types
  10. /// </summary>
  11. public abstract partial class SchemaType
  12. {
  13. #region constructor
  14. protected SchemaType(Context ctx) { _Owner = ctx; }
  15. #endregion
  16. #region data
  17. /// <summary>
  18. /// context where this type is stored
  19. /// </summary>
  20. private readonly Context _Owner;
  21. /// <summary>
  22. /// identifier used for serialization and deserialization
  23. /// </summary>
  24. public abstract string PersistentName { get; }
  25. #endregion
  26. #region properties
  27. public Context Owner => _Owner;
  28. #endregion
  29. }
  30. [System.Diagnostics.DebuggerDisplay("{PersistentName}")]
  31. public sealed class StringType : SchemaType
  32. {
  33. #region constructor
  34. internal StringType(Context ctx) : base(ctx) { }
  35. #endregion
  36. #region properties
  37. public override string PersistentName => typeof(String).Name;
  38. #endregion
  39. }
  40. [System.Diagnostics.DebuggerDisplay("{PersistentName}")]
  41. public sealed class ObjectType : SchemaType
  42. {
  43. #region constructor
  44. internal ObjectType(Context ctx) : base(ctx) { }
  45. #endregion
  46. #region properties
  47. public override string PersistentName => typeof(Object).Name;
  48. #endregion
  49. }
  50. [System.Diagnostics.DebuggerDisplay("{PersistentName}")]
  51. public sealed class BlittableType : SchemaType
  52. {
  53. #region constructor
  54. internal BlittableType(Context ctx, TypeInfo t, bool isNullable) : base(ctx)
  55. {
  56. if (t == typeof(String).GetTypeInfo()) isNullable = false;
  57. _Type = t;
  58. _IsNullable = isNullable;
  59. }
  60. #endregion
  61. #region data
  62. // https://en.wikipedia.org/wiki/Blittable_types
  63. private readonly TypeInfo _Type;
  64. private readonly Boolean _IsNullable;
  65. #endregion
  66. #region properties
  67. public TypeInfo DataType => _Type;
  68. public bool IsNullable => _IsNullable;
  69. public override string PersistentName => _IsNullable ? $"{_Type.Name}?" : _Type.Name;
  70. #endregion
  71. }
  72. [System.Diagnostics.DebuggerDisplay("enum {PersistentName}")]
  73. public sealed class EnumType : SchemaType
  74. {
  75. #region constructor
  76. internal EnumType(Context ctx, string name, bool isNullable) : base(ctx)
  77. {
  78. _PersistentName = name;
  79. _IsNullable = isNullable;
  80. }
  81. #endregion
  82. #region data
  83. private readonly String _PersistentName;
  84. private readonly Boolean _IsNullable;
  85. private bool _UseIntegers;
  86. private readonly Dictionary<string, int> _Values = new Dictionary<string, int>();
  87. #endregion
  88. #region properties
  89. public bool IsNullable => _IsNullable;
  90. public override string PersistentName => _PersistentName;
  91. public bool UseIntegers { get => _UseIntegers; set => _UseIntegers = value; }
  92. public SchemaType ItemType => UseIntegers ? (SchemaType)Owner.UseBlittable(typeof(int).GetTypeInfo()) : Owner.UseString();
  93. public IEnumerable<KeyValuePair<string, int>> Values => _Values;
  94. #endregion
  95. #region API
  96. public void SetValue(string key, int val) { _Values[key] = val; }
  97. #endregion
  98. }
  99. [System.Diagnostics.DebuggerDisplay("{PersistentName}")]
  100. public sealed class ArrayType : SchemaType
  101. {
  102. #region constructor
  103. internal ArrayType(Context ctx, SchemaType element) : base(ctx)
  104. {
  105. _ItemType = element;
  106. }
  107. #endregion
  108. #region data
  109. private readonly SchemaType _ItemType;
  110. public SchemaType ItemType => _ItemType;
  111. #endregion
  112. #region properties
  113. public override string PersistentName => $"{_ItemType.PersistentName}[]";
  114. #endregion
  115. }
  116. [System.Diagnostics.DebuggerDisplay("{PersistentName}")]
  117. public sealed class DictionaryType : SchemaType
  118. {
  119. #region lifecycle
  120. internal DictionaryType(Context ctx, SchemaType key,SchemaType val) : base(ctx)
  121. {
  122. _KeyType = key;
  123. _ValueType = val;
  124. }
  125. #endregion
  126. #region data
  127. private readonly SchemaType _KeyType;
  128. private readonly SchemaType _ValueType;
  129. #endregion
  130. #region properties
  131. public SchemaType KeyType => _KeyType;
  132. public SchemaType ValueType => _ValueType;
  133. public override string PersistentName => $"<{_KeyType.PersistentName},{_ValueType.PersistentName}>[]";
  134. #endregion
  135. }
  136. [System.Diagnostics.DebuggerDisplay("{FieldType.PersistentName} {PersistentName}")]
  137. public sealed class FieldInfo
  138. {
  139. #region lifecycle
  140. internal FieldInfo(ClassType owner, string name)
  141. {
  142. _Owner = owner;
  143. _PersistentName = name;
  144. }
  145. #endregion
  146. #region data
  147. private readonly ClassType _Owner;
  148. private readonly String _PersistentName;
  149. private SchemaType _FieldType;
  150. private Object _DefaultValue;
  151. private Object _MinimumValue;
  152. private Object _MaximumValue;
  153. private int _MinItems;
  154. private int _MaxItems;
  155. #endregion
  156. #region properties
  157. public ClassType DeclaringClass => _Owner;
  158. public string PersistentName => _PersistentName;
  159. public SchemaType FieldType { get => _FieldType; set => _FieldType = value; }
  160. public Object DefaultValue { get => _DefaultValue; set => _DefaultValue = value; }
  161. public Object MinimumValue { get => _MinimumValue; set => _MinimumValue = value; }
  162. public Object MaximumValue { get => _MaximumValue; set => _MaximumValue = value; }
  163. public int MinItems { get => _MinItems; set => _MinItems = value; }
  164. public int MaxItems { get => _MaxItems; set => _MaxItems = value; }
  165. #endregion
  166. #region fluent api
  167. public FieldInfo SetDataType(SchemaType type) { _FieldType = type; return this; }
  168. public FieldInfo SetDataType(Type type, bool isNullable)
  169. {
  170. _FieldType = DeclaringClass.Owner.UseBlittable(type.GetTypeInfo(), isNullable);
  171. return this;
  172. }
  173. public FieldInfo RemoveDefaultValue() { _DefaultValue = null; return this; }
  174. public FieldInfo SetDefaultValue(string defval) { _DefaultValue = defval; return this; }
  175. public FieldInfo SetLimits(Decimal? min, Decimal? max) { _MinimumValue = min; _MaximumValue = max; return this; }
  176. public FieldInfo SetItemsRange(int min, int max = int.MaxValue) { _MinItems = min; _MaxItems = max; return this; }
  177. #endregion
  178. #region comparer helper
  179. private sealed class _Comparer : IEqualityComparer<FieldInfo>
  180. {
  181. public bool Equals(FieldInfo x, FieldInfo y)
  182. {
  183. return x._PersistentName == y._PersistentName;
  184. }
  185. public int GetHashCode(FieldInfo obj)
  186. {
  187. return obj._PersistentName.GetHashCode();
  188. }
  189. }
  190. private static readonly _Comparer _DefaultComparer = new _Comparer();
  191. public static IEqualityComparer<FieldInfo> Comparer => _DefaultComparer;
  192. #endregion
  193. }
  194. [System.Diagnostics.DebuggerDisplay("class {PersistentName} : {BaseClass.PersistentName}")]
  195. public sealed class ClassType : SchemaType
  196. {
  197. #region constructor
  198. internal ClassType(Context ctx, string name) : base(ctx)
  199. {
  200. _PersistentName = name;
  201. }
  202. #endregion
  203. #region data
  204. private readonly String _PersistentName;
  205. private readonly HashSet<FieldInfo> _Fields = new HashSet<FieldInfo>(FieldInfo.Comparer);
  206. private ClassType _BaseClass;
  207. public override string PersistentName => _PersistentName;
  208. public ClassType BaseClass { get => _BaseClass; set => _BaseClass = value; }
  209. public IEnumerable<FieldInfo> Fields => _Fields;
  210. #endregion
  211. #region API
  212. public FieldInfo UseField(string name)
  213. {
  214. var f = new FieldInfo(this, name);
  215. _Fields.Add(f);
  216. return _Fields.FirstOrDefault(item => item.PersistentName == name);
  217. }
  218. #endregion
  219. }
  220. /// <summary>
  221. /// not used
  222. /// </summary>
  223. public sealed class ReferenceType : SchemaType
  224. {
  225. #region constructor
  226. internal ReferenceType(Context ctx, SchemaType refType) : base(ctx)
  227. {
  228. _ReferencedType = refType;
  229. }
  230. #endregion
  231. #region data
  232. // In code it has the representation List<Node>();
  233. // In serialization, it has the representation List<int>();
  234. private readonly SchemaType _ReferencedType;
  235. public override string PersistentName => throw new NotImplementedException();
  236. #endregion
  237. }
  238. }