public static void BuildHashCodesTable(Type type, out int[] values, out ulong[] hashCodes) { var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); var enumValues = fields.Select(field => ConvertToInt(Enum.Parse(type, field.Name), type.GetEnumUnderlyingType())).ToArray(); var uniqueValues = new HashSet <int>(enumValues).ToArray(); var nameHashes = GroBufHelpers.CalcHashesAndCheck(fields.Select(DataMember.Create)); var hashSet = new HashSet <uint>(); for (var x = (uint)enumValues.Length;; ++x) { hashSet.Clear(); var ok = true; foreach (var value in uniqueValues) { var item = ((uint)value) % x; if (hashSet.Contains(item)) { ok = false; break; } hashSet.Add(item); } if (!ok) { continue; } hashCodes = new ulong[x]; values = new int[x]; for (var i = 0; i < x; ++i) { values[i] = -1; } for (var i = 0; i < enumValues.Length; i++) { var value = enumValues[i]; var index = ((uint)value) % x; hashCodes[index] = nameHashes[i]; values[index] = value; } break; } }
public IGroBufCustomSerializer Get(Type declaredType, Func <Type, IGroBufCustomSerializer> factory, IGroBufCustomSerializer baseSerializer) { var attribute = declaredType.GetCustomAttributes(typeof(GroBufCustomSerializationAttribute), false).FirstOrDefault() as GroBufCustomSerializationAttribute; if (attribute == null) { return(null); } Type customSerializerType = attribute.CustomSerializerType ?? declaredType; MethodInfo customSizeCounter = GroBufHelpers.GetMethod <GroBufSizeCounterAttribute>(customSerializerType); if (customSizeCounter == null) { throw new MissingMethodException("Missing grobuf custom size counter for type '" + customSerializerType + "'"); } MethodInfo writer = GroBufHelpers.GetMethod <GroBufWriterAttribute>(customSerializerType); if (writer == null) { throw new MissingMethodException("Missing grobuf custom writer for type '" + customSerializerType + "'"); } MethodInfo reader = GroBufHelpers.GetMethod <GroBufReaderAttribute>(customSerializerType); if (reader == null) { throw new MissingMethodException("Missing grobuf custom reader for type '" + customSerializerType + "'"); } var sizeCounterDelegate = (SizeCounterDelegate)customSizeCounter.Invoke( null, new object[] { (Func <Type, SizeCounterDelegate>)(type => ((o, empty, context) => factory(type).CountSize(o, empty, context))), (SizeCounterDelegate)(baseSerializer.CountSize) }); var writerDelegate = (WriterDelegate)writer.Invoke( null, new object[] { (Func <Type, WriterDelegate>)(type => ((object o, bool empty, IntPtr result, ref int index, WriterContext context) => factory(type).Write(o, empty, result, ref index, context))), (WriterDelegate)(baseSerializer.Write) }); var readerDelegate = (ReaderDelegate)reader.Invoke( null, new object[] { (Func <Type, ReaderDelegate>)(type => ((IntPtr data, ref int index, ref object result, ReaderContext context) => factory(type).Read(data, ref index, ref result, context))), (ReaderDelegate)(baseSerializer.Read) }); return(new GroBufCustomSerializerByAttribute(sizeCounterDelegate, writerDelegate, readerDelegate)); }
public static void BuildValuesTable(Type type, out int[] values, out ulong[] hashCodes) { var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); var arr = fields.Select(field => ConvertToInt(Enum.Parse(type, field.Name), type.GetEnumUnderlyingType())).ToArray(); var hashes = GroBufHelpers.CalcHashesAndCheck(fields.Select(DataMember.Create)); var hashSet = new HashSet <uint>(); for (var x = (uint)hashes.Length;; ++x) { hashSet.Clear(); var ok = true; foreach (var hash in hashes) { var item = (uint)(hash % x); if (hashSet.Contains(item)) { ok = false; break; } hashSet.Add(item); } if (!ok) { continue; } hashCodes = new ulong[x]; values = new int[x]; for (var i = 0; i < hashes.Length; i++) { var hash = hashes[i]; var index = (int)(hash % x); hashCodes[index] = hash; values[index] = (int)arr.GetValue(i); } return; } }