Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#@ template debug="false" hostspecific="true" language="C#" #>
- <#@ assembly name="System.Core" #>
- <#@ import namespace="System.Linq" #>
- <#@ import namespace="System.IO" #>
- <#@ import namespace="System.Text" #>
- <#@ import namespace="System.Security" #>
- <#@ import namespace="System.Collections.Generic" #>
- <#@ import namespace="System.Collections.ObjectModel" #>
- <#@ output extension=".cs" #>
- <#
- var basePath = Path.GetFullPath(Host.ResolveAssemblyReference("$(ProjectDir)"));
- var structureDefinitions = ParseStructureDeclarations(basePath, @"Messaging\Channels\Ipc\Packets\*.struct");
- var blittableTypesCount = 0;
- do
- {
- blittableTypesCount = BlittableTypeSizes.Count;
- foreach (var structureDefinition in structureDefinitions)
- {
- if (BlittableTypeSizes.ContainsKey(structureDefinition.Name))
- continue;
- if (structureDefinition.Type != "struct")
- continue;
- var maxOffset = 0;
- var offset = 0;
- foreach (var field in structureDefinition.Fields)
- {
- var fieldSize = 0;
- if (BlittableTypeSizes.TryGetValue(field.Type, out fieldSize) == false)
- goto nextStruct;
- if(field.Offset > 0)
- offset = field.Offset;
- offset += fieldSize;
- maxOffset = Math.Max(offset, maxOffset);
- }
- BlittableTypeSizes[structureDefinition.Name] = maxOffset;
- nextStruct:
- continue;
- }
- } while (blittableTypesCount != BlittableTypeSizes.Count);
- #>//------------------------------------------------------------------------------
- // <auto-generated>
- // This code was generated by a tool.
- // Changes to this file may cause incorrect behavior and will be lost if
- // the code is regenerated.
- // </auto-generated>
- //------------------------------------------------------------------------------
- // ReSharper disable All
- using System;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Runtime.CompilerServices;
- using Pluto.Utils.Serialization.Binary;
- namespace Pluto
- {
- public static class BinarySerialiableTypes
- {
- public static void Register()
- {
- <#
- foreach(var structure in structureDefinitions)
- {
- #> RuntimeHelpers.RunClassConstructor(typeof(<#= @structure.Namespace #>.<#= @structure.Name #>).TypeHandle);
- <#
- }
- #> }
- }
- }
- <#
- foreach(var structure in structureDefinitions)
- {
- var size = 0;
- var isBlittable = BlittableTypeSizes.TryGetValue(structure.Name, out size);
- var offset = 0;
- #>
- namespace <#= structure.Namespace #>
- {
- <#= string.IsNullOrWhiteSpace(structure.Description) ? "" : "/// <summary>" + SecurityElement.Escape(structure.Description.Replace("\n", ""))+ "</summary>" #>
- <#= isBlittable ? "[StructLayout(LayoutKind.Explicit, Size = " + size + ", Pack = 1)]" : "" #>
- public partial <#= @structure.Type #> <#= @structure.Name #>
- {
- <#
- foreach(var field in structure.Fields)
- {
- if(field.Offset > 0)
- offset = field.Offset;
- #> <#= isBlittable ? "[FieldOffset(" + offset + ")]" : "" #><#= field.Type == "Bool" || field.Type == "Boolean" ? "[MarshalAs(UnmanagedType.I1)]" : "" #>
- public <#= field.Type #> <#= field.Name #>;
- <#
- var fieldSize = 0;
- BlittableTypeSizes.TryGetValue(field.Type, out fieldSize);
- offset += fieldSize;
- }
- #>
- static <#= @structure.Name #>()
- {
- TypeSerializer<<#= structure.Name #>>.Register<Serializer>();
- }
- public <#= structure.Name #>(<#= string.Join(", ", structure.Fields.Select(f => f.Type + " " + f.Name.ToLowerInvariant()).ToArray()) #>)
- {
- <#
- foreach(var field in structure.Fields)
- {
- #> this.<#= field.Name #> = <#= field.Name.ToLowerInvariant() #>;
- <#
- }
- #>
- }
- public override int GetHashCode()
- {
- return unchecked
- (
- <#
- foreach(var field in structure.Fields)
- {
- #> (this.<#= field.Name #> == default(<#= field.Type #>) ? 0 : this.<#= field.Name #>.GetHashCode()) <#= structure.Fields.Last() == field ? "" : "+" #>
- <#
- }
- #>
- );
- }
- public override bool Equals(object value)
- {
- return value is <#= structure.Name #> && this.Equals((<#= structure.Name #>)value);
- }
- public bool Equals(<#= structure.Name #> other)
- {
- <#
- if (structure.Type == "class")
- {#>
- if (other == null)
- return false;
- else if (ReferenceEquals(this, other))
- return true;
- <#
- }
- #>
- return
- (
- <#
- foreach(var field in structure.Fields)
- {
- #> object.Equals(this.<#= field.Name #>, other.<#= field.Name #>) <#= structure.Fields.Last() == field ? "" : "&&" #>
- <#
- }
- #> );
- }
- public override string ToString()
- {
- return
- (
- "<#= structure.Name #>, " +
- <#
- foreach(var field in structure.Fields)
- {
- var fieldValue = "this." + field.Name;
- if(field.Type.EndsWith("[]"))
- fieldValue = "(this." + field.Name + " != null ? string.Join(\", \", Array.ConvertAll(this." + field.Name + ", v => Convert.ToString(v))) : \"<null>\")";
- #> "<#= field.Name #>: " + <#= fieldValue #> <#= structure.Fields.Last() == field ? "" : "+ \", \" + " #>
- <#
- }
- #>
- );
- }
- public sealed class Serializer : <#= isBlittable ? "Blittable" : "" #>TypeSerializer<<#= @structure.Name #>>
- {
- public override int Write(ref <#= @structure.Name #> value, BinaryWriter writer)
- {
- var size = 0;
- <#
- offset = 0;
- foreach(var field in structure.Fields)
- {
- if(field.Offset > 0 && field.Offset != offset)
- {
- if (field.Offset < offset) throw new NotSupportedException("Negative field offset is not supported.");
- var hole = field.Offset - offset;
- #> size += <#= hole #>;
- <#
- while (hole > 0)
- {
- var holeType = "";
- switch(hole)
- {
- case 1: holeType = "Byte"; hole -= 1; break;
- case 2:
- case 3: holeType = "Int16"; hole -= 2; break;
- case 4:
- case 5:
- case 6:
- case 7: holeType = "Int32"; hole -= 4; break;
- default: holeType = "Int64"; hole -= 8; break;
- }
- #> writer.Write((<#= holeType #>)0);
- <#
- }
- offset = field.Offset;
- }
- #>
- size += TypeSerializer<<#= field.Type #>>.Instance.Write(ref value.<#= field.Name #>, writer);
- <#
- var fieldSize = 0;
- BlittableTypeSizes.TryGetValue(field.Type, out fieldSize);
- offset += fieldSize;
- }
- #>
- return size;
- }
- public override int Write(ref <#= @structure.Name #> value, WriteBuffer writeBuffer)
- {
- <#
- if (!isBlittable)
- {
- #> var size = 0;
- <#
- foreach(var field in structure.Fields)
- {
- if (field.Offset > 0 && field.Offset != offset)
- {
- if (field.Offset < offset) throw new NotSupportedException("Negative field offset is not supported.");
- var hole = field.Offset - offset;
- #> size += <#= hole #>;
- writer.WriteByte(0, <#= hole #>);
- <#
- offset = field.Offset;
- }
- #> size += TypeSerializer<<#= field.Type #>>.Instance.Write(ref value.<#= field.Name #>, writeBuffer);
- <#
- }
- #>
- return size;
- <#
- }
- else
- {
- #>
- writeBuffer.EnsureRange(<#= size #>);
- var buffer = writeBuffer.Buffer;
- unsafe
- {
- fixed (byte* b = buffer)
- *((<#= @structure.Name #>*)(b + writeBuffer.Offset)) = value;
- }
- writeBuffer.Offset += <#= size #>;
- writeBuffer.BytesAvailable -= <#= size #>;
- return <#= size #>;
- <#
- }
- #>
- }
- public override int Read(out <#= @structure.Name #> value, BinaryReader reader)
- {
- var size = 0;
- <#
- offset = 0;
- foreach(var field in structure.Fields)
- {
- if(field.Offset > 0 && field.Offset != offset)
- {
- if (field.Offset < offset) throw new NotSupportedException("Negative field offset is not supported.");
- var hole = field.Offset - offset;
- #>
- size += <#= hole #>;
- <#
- while (hole > 0)
- {
- var holeType = "";
- switch(hole)
- {
- case 1: holeType = "Byte"; hole -= 1; break;
- case 2:
- case 3: holeType = "Int16"; hole -= 2; break;
- case 4:
- case 5:
- case 6:
- case 7: holeType = "Int32"; hole -= 4; break;
- default: holeType = "Int64"; hole -= 8; break;
- }
- #> reader.Read<#= holeType #>();
- <#
- }
- offset = field.Offset;
- }
- #>
- size += TypeSerializer<<#= field.Type #>>.Instance.Read(out value.<#= field.Name #>, reader);
- <#
- var fieldSize = 0;
- BlittableTypeSizes.TryGetValue(field.Type, out fieldSize);
- offset += fieldSize;
- }
- #>
- return size;
- }
- public override int Read(out <#= @structure.Name #> value, ReadBuffer readBuffer)
- {
- <#
- if (!isBlittable)
- {
- #> var size = 0;
- <#
- foreach(var field in structure.Fields)
- {
- if (field.Offset > 0 && field.Offset != offset)
- {
- if (field.Offset < offset) throw new NotSupportedException("Negative field offset is not supported.");
- var hole = field.Offset - offset;
- #> size += <#= hole #>;
- readBuffer.SkipBytes(<#= hole #>);
- <#
- offset = field.Offset;
- }
- #>
- size += TypeSerializer<<#= field.Type #>>.Instance.Read(out value.<#= field.Name #>, readBuffer);
- <#
- }
- #>
- return size;
- <#
- }
- else
- {
- #>
- readBuffer.EnsureRange(<#= size #>);
- var buffer = readBuffer.Buffer;
- unsafe
- {
- fixed (byte* b = buffer)
- value = *((<#= @structure.Name #>*)(b + readBuffer.Offset));
- }
- readBuffer.Offset += <#= size #>;
- readBuffer.BytesAvailable -= <#= size #>;
- return <#= size #>;
- <#
- }
- #>
- }
- public override int Measure(ref <#= @structure.Name #> value)
- {
- <#
- if (!isBlittable)
- {
- #>
- var size = 0;
- <#
- foreach(var field in structure.Fields)
- {
- if (field.Offset > 0 && field.Offset != offset)
- {
- if (field.Offset < offset) throw new NotSupportedException("Negative field offset is not supported.");
- var hole = field.Offset - offset;
- #> size += <#= hole #>;
- <#
- offset = field.Offset;
- }
- #>
- size += TypeSerializer<<#= field.Type #>>.Instance.Measure(ref value.<#= field.Name #>);
- <#
- }
- #>
- return size;
- <#
- }
- else
- {
- #>
- return <#= size #>;
- <#
- }
- #>
- }
- }
- }
- }
- <#
- }
- #>
- <#+
- private List<StructureDefinition> ParseStructureDeclarations(string basePath, string pattern)
- {
- var files = Directory.GetFiles(basePath, pattern, SearchOption.AllDirectories);
- var structures = new List<StructureDefinition>();
- const int STATE_START = 0;
- const int STATE_DEFINITION = 1;
- const int STATE_NAME = 2;
- const int STATE_STRUCT_BODY_START = 3;
- const int STATE_STRUCT_BODY_FIELD_TYPE = 4;
- const int STATE_STRUCT_BODY_FIELD_NAME = 5;
- const int STATE_STRUCT_BODY_FIELD_OFFSET_START = 6;
- const int STATE_STRUCT_BODY_FIELD_OFFSET = 7;
- const int STATE_STRUCT_BODY_FIELD_END = 8;
- const int STATE_STRUCT_BODY_FIELD_COMPLETE = 9;
- const int STATE_STRUCT_COMPLETE = 10;
- foreach (var file in files)
- {
- var fileName = Path.GetFileName(file);
- var content = File.ReadAllText(file, Encoding.UTF8);
- var state = STATE_START;
- var structDescription = default(string);
- var structName = default(string);
- var structNamespace = "Pluto." + Path.GetDirectoryName(file).Substring(basePath.Length).Replace('\\', '.').Replace('/', '.');
- var structType = default(string);
- var fieldType = default(string);
- var fieldName = default(string);
- var fieldOffset = default(string);
- var fields = new List<FieldDefinition>();
- var chars = new StringBuilder();
- for (var offset = 0; offset < content.Length; offset++)
- {
- var @char = content[offset];
- switch (state)
- {
- case STATE_START:
- if (char.IsWhiteSpace(@char))
- continue;
- chars.Append(@char);
- state = STATE_DEFINITION;
- break;
- case STATE_DEFINITION:
- if (chars.Length > 0 && char.IsWhiteSpace(@char))
- {
- structType = chars.ToString();
- switch (structType)
- {
- case "struct":
- case "class": state = STATE_NAME; break;
- default: throw new InvalidOperationException(string.Format("Unknown definition '{0}' at '{1}:{2}'.", chars.ToString(), fileName, offset));
- }
- chars.Length = 0;
- continue;
- }
- else if (char.IsWhiteSpace(@char))
- continue;
- chars.Append(@char);
- break;
- case STATE_NAME:
- if (chars.Length > 0 && (char.IsWhiteSpace(@char) || @char == '{'))
- {
- state = @char == '{' ? STATE_STRUCT_BODY_FIELD_TYPE : STATE_STRUCT_BODY_START;
- structName = chars.ToString();
- chars.Length = 0;
- continue;
- }
- else if (char.IsWhiteSpace(@char))
- continue;
- chars.Append(@char);
- break;
- case STATE_STRUCT_BODY_START:
- if (char.IsWhiteSpace(@char))
- continue;
- else if (@char == '{')
- state = STATE_STRUCT_BODY_FIELD_TYPE;
- else
- throw new InvalidOperationException(string.Format("Invalid syntax '{0}' at '{1}:{2}'.", @char, fileName, offset));
- break;
- case STATE_STRUCT_BODY_FIELD_TYPE:
- if (chars.Length > 0 && char.IsWhiteSpace(@char))
- {
- state = STATE_STRUCT_BODY_FIELD_NAME;
- fieldType = chars.ToString();
- chars.Length = 0;
- }
- else if (@char == '}')
- state = STATE_STRUCT_COMPLETE;
- else if (char.IsWhiteSpace(@char))
- continue;
- else
- chars.Append(@char);
- break;
- case STATE_STRUCT_BODY_FIELD_NAME:
- if (chars.Length > 0 && (char.IsWhiteSpace(@char) || @char == ':' || @char == ',' || @char == '}'))
- {
- if (char.IsWhiteSpace(@char))
- state = STATE_STRUCT_BODY_FIELD_OFFSET_START;
- else if (@char == ':')
- state = STATE_STRUCT_BODY_FIELD_OFFSET;
- else
- state = STATE_STRUCT_BODY_FIELD_COMPLETE;
- fieldName = chars.ToString();
- chars.Length = 0;
- }
- else if (char.IsWhiteSpace(@char))
- continue;
- else
- chars.Append(@char);
- break;
- case STATE_STRUCT_BODY_FIELD_OFFSET_START:
- if (char.IsWhiteSpace(@char))
- continue;
- else if (@char == ':')
- state = STATE_STRUCT_BODY_FIELD_OFFSET;
- else if (@char == ',' || @char == '}')
- state = STATE_STRUCT_BODY_FIELD_COMPLETE;
- else
- throw new InvalidOperationException(string.Format("Invalid syntax '{0}' at '{1}:{2}'.", @char, fileName, offset));
- break;
- case STATE_STRUCT_BODY_FIELD_OFFSET:
- if (chars.Length > 0 && (char.IsWhiteSpace(@char) || @char == ',' || @char == '}'))
- {
- if (char.IsWhiteSpace(@char))
- state = STATE_STRUCT_BODY_FIELD_END;
- else
- state = STATE_STRUCT_BODY_FIELD_COMPLETE;
- fieldOffset = chars.ToString();
- chars.Length = 0;
- }
- else if (char.IsWhiteSpace(@char))
- continue;
- else
- chars.Append(@char);
- break;
- case STATE_STRUCT_BODY_FIELD_END:
- if (char.IsWhiteSpace(@char))
- continue;
- else if (@char == ',' || @char == '}')
- state = STATE_STRUCT_BODY_FIELD_COMPLETE;
- else
- throw new InvalidOperationException(string.Format("Invalid syntax '{0}' at '{1}:{2}'.", @char, fileName, offset));
- break;
- }
- if (state == STATE_STRUCT_BODY_FIELD_COMPLETE)
- {
- fields.Add(new FieldDefinition(fieldName, fieldType, string.IsNullOrEmpty(fieldOffset) ? -1 : int.Parse(fieldOffset)));
- fieldName = null;
- fieldType = null;
- fieldOffset = null;
- if (@char == '}')
- state = STATE_STRUCT_COMPLETE;
- else if (@char == ',')
- state = STATE_STRUCT_BODY_FIELD_TYPE;
- else
- state = STATE_STRUCT_BODY_FIELD_END;
- }
- if (state == STATE_STRUCT_COMPLETE)
- {
- structures.Add(new StructureDefinition(structType, structNamespace, structName, structDescription, fields));
- state = STATE_START;
- }
- }
- }
- return structures;
- }
- private readonly Dictionary<string, int> BlittableTypeSizes = new Dictionary<string, int>(StringComparer.Ordinal)
- {
- {"Boolean", 1},
- {"bool", 1},
- {"Byte", 1},
- {"byte", 1},
- {"SByte", 1},
- {"sbyte", 1},
- {"Int16", 2},
- {"short", 2},
- {"UInt16", 2},
- {"ushort", 2},
- {"Int32", 4},
- {"int", 4},
- {"UInt32", 4},
- {"uint", 4},
- {"Int64", 8},
- {"long", 8},
- {"UInt64", 8},
- {"ulong", 8},
- {"Single", 4},
- {"float", 4},
- {"Double", 8},
- {"double", 8},
- {"Сhar", 2},
- {"char", 2},
- {"Guid", 16},
- {"TimeSpan", 8},
- };
- private class StructureDefinition
- {
- public readonly string Type;
- public readonly string Name;
- public readonly string Namespace;
- public readonly string Description;
- public ReadOnlyCollection<FieldDefinition> Fields;
- public StructureDefinition(string type, string @namespace, string name, string description, List<FieldDefinition> fields)
- {
- this.Type = type;
- this.Namespace = @namespace;
- this.Name = name;
- this.Description = description;
- this.Fields = new ReadOnlyCollection<FieldDefinition>(fields);
- }
- public override string ToString()
- {
- return string.Format("struct {0} {{ {1} }}", this.Name, string.Join(", ", this.Fields));
- }
- }
- private class FieldDefinition
- {
- public readonly string Name;
- public readonly string Type;
- public readonly int Offset;
- public FieldDefinition(string name, string type, int offset)
- {
- this.Name = name;
- this.Type = type;
- this.Offset = offset;
- }
- public override string ToString()
- {
- if (this.Offset < 0)
- return this.Type + " " + this.Name;
- else
- return this.Type + " " + this.Name + ": " + this.Offset;
- }
- }
- #>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement