public static T Read2(TProtocol iprot, T value) { IProtoColumn <T>[] columns = instance.Value.columns; iprot.IncrementRecursionDepth(); try { iprot.ReadStructBegin(); while (true) { TField field = iprot.ReadFieldBegin(); if (field.Type == TType.Stop) { break; } if (field.ID < columns.Length) { IProtoColumn <T> column = columns[field.ID]; column.Read(iprot, value); } else { TProtocolUtil.Skip(iprot, field.Type); } iprot.ReadFieldEnd(); } iprot.ReadStructEnd(); return(value); } finally { iprot.DecrementRecursionDepth(); } }
public static void Write(XmlWriter writer, T proto) { IProtoColumn <T>[] columns = instance.Value.columns; for (int index = 0; index < columns.Length; index++) { IProtoColumn <T> column = columns[index]; if (column != null) { column.Write(writer, proto); } } }
public static void Write(JsonWriter writer, T proto) { IProtoColumn <T>[] columns = instance.Value.columns; writer.WriteStartObject(); for (int index = 0; index < columns.Length; index++) { IProtoColumn <T> column = columns[index]; if (column != null) { column.Write(writer, proto); } } writer.WriteEndObject(); }
/// <summary> /// Serialize a tuple into stream. /// /// The following data are writen into the stream /// 1. bitmask bytes length /// 2. bitmarks bytes /// 3. serialized value for each column in columns masks. /// /// </summary> /// <typeparam name="T">tuple type</typeparam> /// <param name="tuple">tuple object</param> /// <param name="stream">the stread to write the tuple into</param> /// <param name="columnMasks">column masks for serialized columns</param> public static void Serialize <T>(this Stream stream, T proto, ProtoSchema schema) { using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) { int bitPos = (int)stream.Position; byte[] bitmarks = new byte[schema.ColumnMasks.Length]; writer.Write((byte)bitmarks.Length); writer.Write(bitmarks, 0, bitmarks.Length); for (int index = 0; index < schema.Columns.Length; index++) { IProtoColumn column = schema.Columns[index]; if (column.ID >= schema.ColumnMasks.Length * 8) { break; } if (!schema.ColumnMasks.GetBitmask(column.ID)) { bitmarks.SetBitmask(column.ID, false); continue; } object value = proto.GetValue(column); if (CommonUtils.Equals(value, column.DefaultValue)) { bitmarks.SetBitmask(column.ID, false); } else { bitmarks.SetBitmask(column.ID, true); column.Write(writer, value); } } int endPos = (int)stream.Position; stream.Position = bitPos; writer.Write((byte)bitmarks.Length); writer.Write(bitmarks, 0, bitmarks.Length); stream.Position = endPos; } }
public static void Write2(TProtocol oprot, T value) { IProtoColumn <T>[] columns = instance.Value.columns; oprot.IncrementRecursionDepth(); try { TStruct struc = new TStruct(typeof(T).Name); oprot.WriteStructBegin(struc); for (int index = 0; index < columns.Length; index++) { IProtoColumn <T> column = columns[index]; if (column != null) { column.Write(oprot, value); } } oprot.WriteFieldStop(); oprot.WriteStructEnd(); } finally { oprot.DecrementRecursionDepth(); } }
/// <summary> /// Get column value /// </summary> /// <param name="proto">proto object</param> /// <param name="column">proto column</param> /// <returns>column value</returns> public static object GetValue(T proto, IProtoColumn column) { return(instance.Value.getters[column.Index](proto)); }
///// <summary> ///// Gets column by column ID ///// </summary> ///// <param name="id">column ID</param> ///// <returns>proto column</returns> //public static IProtoColumn GetColumn(int id) //{ // return Proto<T>.Columns[id - 1]; //} public static bool TryGetColumn(string name, bool ignoreCase, out IProtoColumn column) { column = Proto <T> .Columns.SingleOrDefault(col => string.Compare(col.Name, name, ignoreCase) == 0); return(column != null); }
/// <summary> /// Create a ProtoColumn for a specific type. /// </summary> /// <param name="type">Column type</param> /// <param name="name">Column name</param> /// <param name="id">Column ID</param> /// <returns>protocolumn object</returns> private static IProtoColumn CreateColumn(Type type, string name, short id = 0, short colIndex = 0, bool nullable = false, bool ignored = false) { if (type == typeof(string)) { return(new StringColumn { Name = name, ID = id, Index = colIndex, Ignored = ignored, }); } else if (type == typeof(bool)) { return(new BooleanColumn { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(byte)) { return(new ByteColumn { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(short)) { return(new Int16Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(ushort)) { return(new UInt16Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(int)) { return(new Int32Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(uint)) { return(new UInt32Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(long)) { return(new Int64Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(ulong)) { return(new UInt64Column { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(double)) { return(new DoubleColumn { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(DateTime)) { return(new DateTimeColumn { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(Guid)) { return(new GuidColumn { Name = name, ID = id, Index = colIndex, IsNullable = nullable, Ignored = ignored, }); } else if (type == typeof(byte[])) { return(new ImageColumn { Name = name, ID = id, Index = colIndex, Ignored = ignored, }); } else if (type.IsArray) { IProtoColumn element = CreateColumn(type.GetElementType(), null); return(new ArrayColumn { Name = name, ID = id, Index = colIndex, Element = element }); } else if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(int?).GetGenericTypeDefinition()) { IProtoColumn protoColumn = CreateColumn(type.GetGenericArguments()[0], name, id, colIndex, nullable: true, ignored: ignored); if (type.GetGenericTypeDefinition().MakeGenericType(protoColumn.ColumnType) != type) { throw new ArgumentException(string.Format("ColumnType of {0} do not match ProtoColumn definition", name)); } return(protoColumn); } else if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(List <int>).GetGenericTypeDefinition()) { IProtoColumn element = CreateColumn(type.GetGenericArguments()[0], null); Type listColumnType = typeof(ListColumn <int>).GetGenericTypeDefinition().MakeGenericType(element.ColumnType); IProtoColumn protoColumn = (IProtoColumn)System.Activator.CreateInstance(listColumnType); TypeUtils.SetProperty(protoColumn, "Name", name); TypeUtils.SetProperty(protoColumn, "ID", id); TypeUtils.SetProperty(protoColumn, "Index", colIndex); TypeUtils.SetProperty(protoColumn, "Ignored", ignored); TypeUtils.SetProperty(protoColumn, "Element", element); return(protoColumn); } else if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(HashSet <int>).GetGenericTypeDefinition()) { IProtoColumn element = CreateColumn(type.GetGenericArguments()[0], null); Type listColumnType = typeof(SetColumn <int>).GetGenericTypeDefinition().MakeGenericType(element.ColumnType); IProtoColumn protoColumn = (IProtoColumn)System.Activator.CreateInstance(listColumnType); TypeUtils.SetProperty(protoColumn, "Name", name); TypeUtils.SetProperty(protoColumn, "ID", id); TypeUtils.SetProperty(protoColumn, "Index", colIndex); TypeUtils.SetProperty(protoColumn, "Ignored", ignored); TypeUtils.SetProperty(protoColumn, "Element", element); return(protoColumn); } else if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(Dictionary <int, int>).GetGenericTypeDefinition()) { IProtoColumn keyElement = CreateColumn(type.GetGenericArguments()[0], null); IProtoColumn valueElement = CreateColumn(type.GetGenericArguments()[1], null); Type mapColumnType = typeof(MapColumn <int, int>).GetGenericTypeDefinition().MakeGenericType(keyElement.ColumnType, valueElement.ColumnType); IProtoColumn protoColumn = (IProtoColumn)System.Activator.CreateInstance(mapColumnType); TypeUtils.SetProperty(protoColumn, "Name", name); TypeUtils.SetProperty(protoColumn, "ID", id); TypeUtils.SetProperty(protoColumn, "Index", colIndex); TypeUtils.SetProperty(protoColumn, "Ignored", ignored); TypeUtils.SetProperty(protoColumn, "KeyElement", keyElement); TypeUtils.SetProperty(protoColumn, "ValueElement", valueElement); return(protoColumn); } else if (type.GetCustomAttribute <ProtoAttribute>() != null) { return(ProtoTypeColumn.CreateColumn(name, id, colIndex, type, ignored, nullable)); } else { throw new ArgumentException(string.Format("failed to create proto column for type {0}", type)); } }
/// <summary> /// Initializes proto schema /// <remarks>ArgumentException could be thrown if ProtoAttribute and ProtoColumn /// attributes are not defined correctly on the type. </remarks> /// </summary> /// <returns>Proto Schema</returns> private static ProtoSchema InitializeSchema(Type type, ref short colIndex) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly; List <IProtoColumn> propColumns = new List <IProtoColumn>(); foreach (PropertyInfo propInfo in type.GetProperties(bindingFlags)) { ProtoColumnAttribute protoColumnAttribute = propInfo.GetCustomAttribute <ProtoColumnAttribute>(); if (protoColumnAttribute != null) { IProtoColumn protoColumn = Proto <T> .CreateColumn(propInfo.PropertyType, propInfo.Name, protoColumnAttribute.ID, colIndex ++, false, protoColumnAttribute.Ignored); propColumns.Add(protoColumn); } } HashSet <string> nameChecks = new HashSet <string>(); HashSet <short> idChecks = new HashSet <short>(); int maxID = 0; int minID = 1; int count = 0; foreach (IProtoColumn col in propColumns.OfType <IProtoColumn>()) { if (!string.IsNullOrEmpty(col.Name)) { if (nameChecks.Contains(col.Name)) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Column name {0} is duplicated", col.Name); } else { nameChecks.Add(col.Name); } } if (idChecks.Contains(col.ID)) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Column ID {0} is duplicated", col.ID); } else { idChecks.Add(col.ID); } count++; minID = Math.Min(col.ID, minID); maxID = Math.Max(col.ID, maxID); } if (minID != 1 || maxID != count) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Column IDs are not consecutive starting from 1"); } byte[] columnMasks = new byte[CommonUtils.BitmaskSize(count + 1)]; if (columnMasks.Length > byte.MaxValue) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "The length of ColumnMasks is greater than {0}", byte.MaxValue); } for (int index = 0; index < columnMasks.Length; index++) { columnMasks[index] = 0; } foreach (IProtoColumn col in propColumns.OfType <IProtoColumn>().Where(c => !c.Ignored)) { CommonUtils.SetBitmask(columnMasks, col.ID, true); } return(new ProtoSchema { Name = type.Name, ColumnMasks = columnMasks, Columns = propColumns.OrderBy(col => col.ID).ToArray(), }); }
/// <summary> /// Set column value /// </summary> /// <param name="proto">proto object</param> /// <param name="column">proto column</param> /// <param name="value">column value</param> public static void SetValue(T proto, IProtoColumn column, object value) { instance.Value.setters[column.Index](proto, value); }
/// <summary> /// Set column value /// </summary> /// <param name="column">proto column</param> /// <param name="value">column value</param> public static void SetValue <T>(this T tuple, IProtoColumn column, object value) { Proto <T> .SetValue(tuple, column, value); }
// /// <summary> // /// Changes context working directory and return a new context // /// </summary> // /// <param name="context">current context</param> // /// <param name="dir">directory to go</param> // /// <returns>new context</returns> // public static IProtoContext ChangeDirectory(this IProtoContext context, string dir) // { // return new ProtoContext(context, dir); // } // /// <summary> // /// Log a trace // /// </summary> // /// <param name="context">component context</param> // /// <param name="component">component name</param> // /// <param name="traceLevel">trace level</param> // /// <param name="category">trace category</param> // /// <param name="msg">message format</param> // /// <param name="args">message arguments</param> // public static void Log(this IProtoContext context, IProtoComponent component, TraceLevel traceLevel, string category, string msg, params object[] args) // { // context.Log(component.Name, traceLevel, category, msg, args); // } /// <summary> /// Get column value /// </summary> /// <param name="column">proto column</param> /// <returns>column value</returns> public static object GetValue <T>(this T tuple, IProtoColumn column) { return(Proto <T> .GetValue(tuple, column)); }
/// <summary> /// Initialize proto metadata /// </summary> /// <returns></returns> private static Proto <T> Initialize() { Type type = typeof(T); if (!type.HasCustomAttribute <ProtoAttribute>()) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "ProtoAttribute is not defined for type {0}", type.FullName); } BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly; List <IProtoColumn <T> > propColumns = new List <IProtoColumn <T> >(); foreach (PropertyInfo propInfo in type.GetProperties(bindingFlags)) { if (propInfo.HasCustomAttribute <ProtoColumnAttribute>()) { IProtoColumn <T> protoColumn = Proto <T> .CreateProtoColumn(propInfo); propColumns.Add(protoColumn); } } HashSet <string> nameChecks = new HashSet <string>(); HashSet <short> idChecks = new HashSet <short>(); int maxID = 0; int minID = 1; int count = 0; foreach (IProtoColumn <T> col in propColumns) { if (!string.IsNullOrEmpty(col.Name)) { if (nameChecks.Contains(col.Name)) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Duplicated column name {0}", col.Name); } else { nameChecks.Add(col.Name); } } if (idChecks.Contains(col.ID)) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Duplicated column ID {0}", col.ID); } else { idChecks.Add(col.ID); } count++; minID = Math.Min(col.ID, minID); maxID = Math.Max(col.ID, maxID); } // if (minID != 1 || maxID != count) // { // throw new ProtoException(ProtoErrorCode.InvalidArgument, "Column IDs are not consecutive starting from 1"); // } if (minID <= 0 && maxID > short.MaxValue) { throw new ProtoException(ProtoErrorCode.InvalidArgument, "Column IDs must be unique and between 1 to 65535"); } IProtoColumn <T>[] columns = new IProtoColumn <T> [maxID + 1]; foreach (IProtoColumn <T> column in propColumns) { columns[column.ID] = column; } Proto <T> proto = new Proto <T>(columns); ParameterExpression iprot = Expression.Parameter(protType); ParameterExpression ivalue = Expression.Parameter(typeof(T)); Expression readExpr = Read(iprot, ivalue, columns); proto.reader = Expression.Lambda <Action <TProtocol, T> >(readExpr, iprot, ivalue).Compile(); ParameterExpression oprot = Expression.Parameter(protType); ParameterExpression ovalue = Expression.Parameter(typeof(T)); Expression writeExpr = Write(oprot, ovalue, columns); proto.writer = Expression.Lambda <Action <TProtocol, T> >(writeExpr, oprot, ovalue).Compile(); return(proto); }