PageRenderTime 25ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace.Pinch/Interlace.Pinch.Dynamic/DynamicPincher.cs

https://bitbucket.org/VahidN/interlace
C# | 299 lines | 231 code | 62 blank | 6 comment | 42 complexity | 66bfc9913d55ec520188322bacf6a2f4 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Interlace.Pinch.Dom;
  5. using Interlace.Pinch.Analysis;
  6. using Interlace.Pinch.Implementation;
  7. using System.IO;
  8. namespace Interlace.Pinch.Dynamic
  9. {
  10. public class DynamicPincher
  11. {
  12. Dictionary<string, DynamicPincherProtocol> _protocols;
  13. public DynamicPincher(string documentPath)
  14. {
  15. Document document = Document.Parse(documentPath);
  16. Compilation compilation = new Compilation();
  17. compilation.AddDocument(document);
  18. compilation.Resolve();
  19. compilation.Number();
  20. _protocols = new Dictionary<string, DynamicPincherProtocol>();
  21. foreach (Protocol protocol in document.Protocols)
  22. {
  23. _protocols[protocol.Name.ToString()] = new DynamicPincherProtocol(protocol);
  24. }
  25. }
  26. public DynamicStructure Decode(string fullName, byte[] encodedBytes)
  27. {
  28. using (MemoryStream stream = new MemoryStream(encodedBytes))
  29. {
  30. return Decode(fullName, stream);
  31. }
  32. }
  33. public DynamicStructure Decode(string fullName, Stream stream)
  34. {
  35. PinchDecoder decoder = new PinchDecoder(stream);
  36. return Decode(fullName, decoder);
  37. }
  38. public DynamicStructure Decode(string fullName, IPinchDecoder decoder)
  39. {
  40. Declaration declaration = ResolveDeclaration(fullName);
  41. if (!(declaration is Structure))
  42. {
  43. throw new PinchException(string.Format("The declaration \"{0}\" is not a structure and can therefore not be decoded."));
  44. }
  45. return Decode((Structure)declaration, decoder);
  46. }
  47. void DecodeMember(DynamicStructure dynamicStructure, StructureMember member, IPinchDecoder decoder)
  48. {
  49. if (member.IsRemoved)
  50. {
  51. decoder.SkipRemoved();
  52. }
  53. else
  54. {
  55. if (member.FieldContainerReference == ContainerType.None)
  56. {
  57. object value = DecodeMemberValue(member, decoder);
  58. dynamicStructure.Members[member.Identifier] = new DynamicMember(member.Identifier, value);
  59. }
  60. else if (member.FieldContainerReference == ContainerType.List)
  61. {
  62. int count = decoder.OpenSequence();
  63. List<object> values = new List<object>();
  64. for (int i = 0; i < count; i++)
  65. {
  66. object value = DecodeMemberValue(member, decoder);
  67. values.Add(value);
  68. }
  69. decoder.CloseSequence();
  70. dynamicStructure.Members[member.Identifier] = new DynamicMember(member.Identifier, values);
  71. }
  72. else
  73. {
  74. throw new NotImplementedException();
  75. }
  76. }
  77. }
  78. object DecodeMemberValue(StructureMember member, IPinchDecoder decoder)
  79. {
  80. // Handle removed members:
  81. if (member.IsRemoved) throw new InvalidOperationException();
  82. // Set up a few handy variables for the decoders:
  83. bool required = (member.Modifier & FieldModifier.Required) != FieldModifier.None;
  84. PinchFieldProperties properties = new PinchFieldProperties(
  85. member.Number, member.Versioning.AddedInVersion, member.Versioning.RemovedInVersion);
  86. if (member.FieldTypeReference is IntrinsicTypeReference)
  87. {
  88. // Handle intrinsic types:
  89. IntrinsicTypeReference reference = (IntrinsicTypeReference)member.FieldTypeReference;
  90. switch (reference.Type)
  91. {
  92. case IntrinsicType.Float32:
  93. return required ? decoder.DecodeRequiredFloat32(properties) : decoder.DecodeOptionalFloat32(properties);
  94. case IntrinsicType.Float64:
  95. return required ? decoder.DecodeRequiredFloat64(properties) : decoder.DecodeOptionalFloat64(properties);
  96. case IntrinsicType.Int8:
  97. return required ? decoder.DecodeRequiredInt8(properties) : decoder.DecodeOptionalInt8(properties);
  98. case IntrinsicType.Int16:
  99. return required ? decoder.DecodeRequiredInt16(properties) : decoder.DecodeOptionalInt16(properties);
  100. case IntrinsicType.Int32:
  101. return required ? decoder.DecodeRequiredInt32(properties) : decoder.DecodeOptionalInt32(properties);
  102. case IntrinsicType.Int64:
  103. return required ? decoder.DecodeRequiredInt64(properties) : decoder.DecodeOptionalInt64(properties);
  104. case IntrinsicType.Decimal:
  105. return required ? decoder.DecodeRequiredDecimal(properties) : decoder.DecodeOptionalDecimal(properties);
  106. case IntrinsicType.Bool:
  107. return required ? decoder.DecodeRequiredBool(properties) : decoder.DecodeOptionalBool(properties);
  108. case IntrinsicType.String:
  109. return required ? decoder.DecodeRequiredString(properties) : decoder.DecodeOptionalString(properties);
  110. case IntrinsicType.Bytes:
  111. return required ? decoder.DecodeRequiredBytes(properties) : decoder.DecodeOptionalBytes(properties);
  112. default:
  113. throw new PinchException("An unknown type was found in the specification object tree.");
  114. }
  115. }
  116. else if (member.FieldTypeReference is DeclarationTypeReference)
  117. {
  118. // Handle structure and enumeration types:
  119. Declaration declaration = ((DeclarationTypeReference)member.FieldTypeReference).Declaration;
  120. if (declaration is Enumeration)
  121. {
  122. int? value = (int?)(required ?
  123. decoder.DecodeRequiredEnumeration(properties) : decoder.DecodeOptionalEnumeration(properties));
  124. if (!value.HasValue) return null;
  125. Enumeration enumeration = (Enumeration)declaration;
  126. string enumerationValueName = null;
  127. foreach (EnumerationMember enumerationMember in enumeration.Members)
  128. {
  129. if (enumerationMember.Number == value.Value)
  130. {
  131. enumerationValueName = enumerationMember.Identifier;
  132. }
  133. }
  134. return new DynamicEnumerationValue(enumeration.Identifier, enumerationValueName, value.Value);
  135. }
  136. else if (declaration is Structure)
  137. {
  138. return Decode((Structure)declaration, decoder);
  139. }
  140. else
  141. {
  142. throw new InvalidOperationException();
  143. }
  144. }
  145. else
  146. {
  147. throw new InvalidOperationException();
  148. }
  149. }
  150. DynamicStructure Decode(Structure structure, IPinchDecoder decoder)
  151. {
  152. if (structure.StructureKind == StructureKind.Message || structure.StructureKind == StructureKind.Structure)
  153. {
  154. // Decode a structure:
  155. DynamicStructure dynamicStructure = new DynamicStructure(structure.QualifiedName.ToString(), structure.Identifier);
  156. foreach (StructureMember member in structure.Members)
  157. {
  158. dynamicStructure.OrderedMemberNames.Add(member.Identifier);
  159. }
  160. int? remainingFieldsNullable = decoder.OpenOptionalSequence();
  161. if (!remainingFieldsNullable.HasValue) return null;
  162. int remainingFields = remainingFieldsNullable.Value;
  163. foreach (StructureMemberVersionGroup group in structure.VersionGroupedMembers)
  164. {
  165. if (remainingFields >= group.Members.Count)
  166. {
  167. foreach (StructureMember member in group.Members)
  168. {
  169. DecodeMember(dynamicStructure, member, decoder);
  170. }
  171. remainingFields -= group.Members.Count;
  172. }
  173. else
  174. {
  175. if (remainingFields != 0) throw new PinchInvalidCodingException();
  176. }
  177. }
  178. if (remainingFields > 0)
  179. {
  180. decoder.SkipFields(remainingFields);
  181. }
  182. decoder.CloseSequence();
  183. return dynamicStructure;
  184. }
  185. else if (structure.StructureKind == StructureKind.Choice)
  186. {
  187. // Decode a choice:
  188. int? choiceMarkerNullable = decoder.DecodeOptionalChoiceMarker();
  189. if (!choiceMarkerNullable.HasValue) return null;
  190. int choiceMarker = choiceMarkerNullable.Value;
  191. DeclarationTypeReference declaration = null;
  192. foreach (StructureMember member in structure.Members)
  193. {
  194. if (member.Number == choiceMarker)
  195. {
  196. declaration = (DeclarationTypeReference)member.FieldTypeReference;
  197. }
  198. }
  199. if (declaration == null)
  200. {
  201. throw new PinchException(
  202. "A structure in a choice could not be found in the specification.");
  203. }
  204. if (!(declaration.Declaration is Structure))
  205. {
  206. throw new PinchException(
  207. "A choice value is a non-structure, which is not supported.");
  208. }
  209. return Decode((Structure)declaration.Declaration, decoder);
  210. }
  211. else
  212. {
  213. throw new InvalidOperationException();
  214. }
  215. }
  216. public Declaration ResolveDeclaration(string fullName)
  217. {
  218. string[] parts = fullName.Split('.');
  219. if (parts.Length < 2) throw new PinchException(string.Format(
  220. "The declaration \"{0}\" was not found in the loaded specification files (and is not a full legal name).", fullName));
  221. string declarationName = parts[parts.Length - 1];
  222. string protocolName = string.Join(".", parts, 0, parts.Length - 1);
  223. if (!_protocols.ContainsKey(protocolName))
  224. {
  225. throw new PinchException(string.Format(
  226. "The protocol containing the declaration \"{0}\" was not found in the loaded specification files.", fullName));
  227. }
  228. Declaration declaration = _protocols[protocolName].FindDeclaration(declarationName);
  229. if (declaration == null)
  230. {
  231. throw new PinchException(string.Format(
  232. "The the declaration \"{0}\" was not found in the loaded specification files.", fullName));
  233. }
  234. return declaration;
  235. }
  236. }
  237. }