PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/AssemblyAnalyzer/Kokomo.Mirror/StructSerializer.cs

#
C# | 351 lines | 315 code | 36 blank | 0 comment | 87 complexity | 2daaa83ede231a391d847cb260fd4048 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Collections;
  8. namespace Kokomo.Mirror
  9. {
  10. class StructSerializer : StructReaderBase
  11. {
  12. public StructSerializer(
  13. Stream stream,
  14. Encoding encoding = null
  15. )
  16. : base(stream)
  17. {
  18. if (encoding == null) encoding = Encoding.Default;
  19. this.BinaryReader = new BinaryReader(stream, encoding);
  20. }
  21. public BinaryReader BinaryReader { get; private set; }
  22. public TStruct ReadStruct<TStruct>()
  23. where TStruct : new()
  24. {
  25. TStruct struc = new TStruct();
  26. this.ReadStruct(struc);
  27. return struc;
  28. }
  29. public object ReadStruct(Type structType)
  30. {
  31. if (structType == null) throw new ArgumentNullException("structType");
  32. object instance = Activator.CreateInstance(structType);
  33. this.ReadStruct(instance);
  34. return instance;
  35. }
  36. public void ReadStruct(object instance)
  37. {
  38. if (instance == null) throw new ArgumentNullException("struc");
  39. BinaryReader reader = this.BinaryReader;
  40. Type structType = instance.GetType();
  41. MemberInfo[] members = structType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  42. Dictionary<string, bool> booleanFieldValues = new Dictionary<string, bool>();
  43. Dictionary<string, int> numericFieldValues = new Dictionary<string, int>();
  44. foreach (var member in members)
  45. {
  46. SerializedConditionAttribute conditionAttribute = (SerializedConditionAttribute)Attribute.GetCustomAttribute(member, typeof(SerializedConditionAttribute));
  47. if (conditionAttribute != null)
  48. {
  49. bool conditionValue = (bool)this.GetPropertyPathValue(instance, conditionAttribute.ConditionPropertyPath);
  50. if (!conditionValue) continue;
  51. }
  52. SerializedOffsetAttribute offsetAttribute = (SerializedOffsetAttribute)Attribute.GetCustomAttribute(member, typeof(SerializedOffsetAttribute));
  53. if (offsetAttribute != null)
  54. {
  55. int offset = Convert.ToInt32(this.GetPropertyPathValue(instance, offsetAttribute.OffsetPropertyName));
  56. this.Stream.Position = offset;
  57. }
  58. PropertyInfo property = member as PropertyInfo;
  59. if (property != null)
  60. {
  61. MethodInfo setter = property.GetSetMethod(true);
  62. if (setter == null) continue;
  63. NonSerializedAttribute nonSerializable = property.GetCustomAttribute<NonSerializedAttribute>();
  64. if (nonSerializable != null) continue;
  65. object propertyValue = null;
  66. SerializerContextFieldAttribute contextFieldAttribute = (SerializerContextFieldAttribute)Attribute.GetCustomAttribute(property, typeof(SerializerContextFieldAttribute));
  67. if (contextFieldAttribute != null)
  68. {
  69. switch (contextFieldAttribute.Field)
  70. {
  71. case SerializerContextField.Position32:
  72. propertyValue = (int)this.Stream.Position;
  73. break;
  74. case SerializerContextField.Position64:
  75. propertyValue = this.Stream.Position;
  76. break;
  77. }
  78. }
  79. else
  80. {
  81. propertyValue = this.ReadPropertyValue(property, property.PropertyType, instance);
  82. }
  83. if (propertyValue != null)
  84. {
  85. setter.Invoke(instance, new object[] { propertyValue });
  86. }
  87. }
  88. }
  89. }
  90. private object ReadPropertyValue(
  91. PropertyInfo property,
  92. Type propertyType,
  93. object instance
  94. )
  95. {
  96. object propertyValue = null;
  97. if (propertyType.IsArray)
  98. {
  99. int? length = this.DetermineLength(property, instance);
  100. propertyValue = this.ReadArray(property, instance, propertyType.GetElementType(), length);
  101. }
  102. else if (propertyType == typeof(string))
  103. {
  104. int? length = this.DetermineLength(property, instance);
  105. propertyValue = this.ReadString(length);
  106. }
  107. else if (propertyType.IsEnum || propertyType.IsPrimitive)
  108. {
  109. propertyValue = this.ReadValue(propertyType);
  110. }
  111. else
  112. {
  113. SerializeSwitchAttribute[] switchAttributes = (SerializeSwitchAttribute[])Attribute.GetCustomAttributes(property, typeof(SerializeSwitchAttribute));
  114. if (switchAttributes.Length > 0)
  115. {
  116. foreach (var switchAttribute in switchAttributes)
  117. {
  118. bool switchValue = (bool)GetPropertyPathValue(instance, switchAttribute.ConditionPropertyPath);
  119. if (switchValue)
  120. {
  121. propertyType = switchAttribute.StructType;
  122. break;
  123. }
  124. }
  125. }
  126. object propertyStruc = Activator.CreateInstance(propertyType);
  127. this.ReadStruct(propertyStruc);
  128. propertyValue = propertyStruc;
  129. }
  130. return propertyValue;
  131. }
  132. private object ReadValue(
  133. Type propertyType
  134. )
  135. {
  136. object propertyValue = null;
  137. if (propertyType.IsPrimitive)
  138. {
  139. propertyValue = ReadPrimitive(propertyType);
  140. }
  141. else if (propertyType.IsEnum)
  142. {
  143. object numericValue = ReadPrimitive(propertyType.GetEnumUnderlyingType());
  144. propertyValue = Enum.ToObject(propertyType, numericValue);
  145. }
  146. else
  147. {
  148. propertyValue = ReadStruct(propertyType);
  149. }
  150. return propertyValue;
  151. }
  152. private object GetPropertyPathValue(object instance, string propertyPath)
  153. {
  154. if (instance == null) throw new ArgumentNullException("instance");
  155. if (propertyPath == null) throw new ArgumentNullException("propertyName");
  156. string[] propertyNames = propertyPath.Split('.');
  157. foreach (var propertyName in propertyNames)
  158. {
  159. PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  160. object value = property.GetValue(instance, null);
  161. if (value == null) break;
  162. instance = value;
  163. }
  164. return instance;
  165. }
  166. private int? DetermineLength(
  167. PropertyInfo property,
  168. object instance
  169. )
  170. {
  171. if (property == null) throw new ArgumentNullException("property");
  172. if (instance == null) throw new ArgumentNullException("instance");
  173. SerializedArrayAttribute serializedStringAttribute = (SerializedArrayAttribute)Attribute.GetCustomAttribute(property, typeof(SerializedArrayAttribute));
  174. if (serializedStringAttribute == null) throw new InvalidOperationException("String property missing SerializedStringAttribute");
  175. BinaryReader reader = this.BinaryReader;
  176. int? length = null;
  177. switch (serializedStringAttribute.LengthEncoding)
  178. {
  179. case ArrayLengthEncoding.Fixed:
  180. length = serializedStringAttribute.FixedLength;
  181. break;
  182. case ArrayLengthEncoding.ByteCountPrefix16:
  183. case ArrayLengthEncoding.ElementCountPrefix16:
  184. length = reader.ReadInt16();
  185. break;
  186. case ArrayLengthEncoding.ByteCountPrefix32:
  187. length = reader.ReadInt32();
  188. break;
  189. case ArrayLengthEncoding.ElementCountPrefix32:
  190. break;
  191. case ArrayLengthEncoding.BytePrefixField:
  192. case ArrayLengthEncoding.ElementPrefixField:
  193. object prefixFieldValue = this.GetPropertyPathValue(instance, serializedStringAttribute.LengthFieldName);
  194. length = Convert.ToInt32(prefixFieldValue);
  195. break;
  196. case ArrayLengthEncoding.ZeroTerminated:
  197. break;
  198. }
  199. return length;
  200. }
  201. private object ReadPrimitive(Type type)
  202. {
  203. if (type == null) throw new ArgumentNullException("type");
  204. object value = null;
  205. BinaryReader reader = this.BinaryReader;
  206. if (type.IsPrimitive)
  207. {
  208. if (type == typeof(int))
  209. {
  210. value = reader.ReadInt32();
  211. }
  212. else if (type == typeof(IntPtr))
  213. {
  214. value = new IntPtr(reader.ReadInt32());
  215. }
  216. else if (type == typeof(uint))
  217. {
  218. value = reader.ReadUInt32();
  219. }
  220. else if (type == typeof(short))
  221. {
  222. value = reader.ReadInt16();
  223. }
  224. else if (type == typeof(ushort))
  225. {
  226. value = reader.ReadUInt16();
  227. }
  228. else if (type == typeof(byte))
  229. {
  230. value = reader.ReadByte();
  231. }
  232. else if (type == typeof(bool))
  233. {
  234. value = reader.ReadBoolean();
  235. }
  236. else if (type == typeof(long))
  237. {
  238. value = reader.ReadInt64();
  239. }
  240. else if (type == typeof(ulong))
  241. {
  242. value = reader.ReadUInt64();
  243. }
  244. else
  245. {
  246. throw new ArgumentException("Unknown type");
  247. }
  248. }
  249. return value;
  250. }
  251. public string ReadString(
  252. int? length
  253. )
  254. {
  255. string str;
  256. if (length.HasValue)
  257. {
  258. char[] chars = this.BinaryReader.ReadChars(length.Value);
  259. str = new string(chars);
  260. }
  261. else
  262. {
  263. StringBuilder builder = new StringBuilder();
  264. for (char c = this.BinaryReader.ReadChar(); c != '\0'; c = this.BinaryReader.ReadChar())
  265. {
  266. builder.Append(c);
  267. }
  268. str = builder.ToString();
  269. }
  270. return str;
  271. }
  272. public TElement[] ReadArray<TElement>(int? length)
  273. {
  274. return (TElement[])this.ReadArray(typeof(TElement), length, ReadValue);
  275. }
  276. protected Array ReadArray(PropertyInfo property, object instance, Type elementType, int? length)
  277. {
  278. return this.ReadArray(elementType, length, t => ReadPropertyValue(property, t, instance));
  279. }
  280. protected Array ReadArray(
  281. Type elementType,
  282. int? length,
  283. Func<Type, object> readerDelegate
  284. )
  285. {
  286. if (elementType == null) throw new ArgumentNullException("elementType");
  287. if (readerDelegate == null) throw new ArgumentNullException("readerDelegate");
  288. Array array;
  289. if (length.HasValue)
  290. {
  291. array = Array.CreateInstance(elementType, length.Value);
  292. for (int i = 0; i < array.Length; i++)
  293. {
  294. object element = readerDelegate(elementType);
  295. array.SetValue(element, i);
  296. }
  297. }
  298. else
  299. {
  300. List<object> list = new List<object>();
  301. object defaultInstance = Activator.CreateInstance(elementType);
  302. object element = null;
  303. while (true)
  304. {
  305. element = readerDelegate(elementType);
  306. if (object.Equals(element, defaultInstance)) break;
  307. list.Add(element);
  308. }
  309. array = Array.CreateInstance(elementType, list.Count);
  310. Array.Copy(list.ToArray(), array, array.Length);
  311. }
  312. return array;
  313. }
  314. }
  315. }