public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { // Get serializer for sub items var keyEncoder = recurse(type.GenericTypeArguments[0]); var valueEncoder = recurse(type.GenericTypeArguments[1]); return(new Func <IDictionary, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } // Serialize elements var output = new EncodeBuffer(); var e = value.GetEnumerator(); UInt64 count = 0; while (e.MoveNext()) { output.Append((EncodeBuffer)keyEncoder.DynamicInvokeTransparent(e.Key)); output.Append((EncodeBuffer)valueEncoder.DynamicInvokeTransparent(e.Value)); count++; } // Encode length output.SetFirst(UnsignedVlq.Encode(count + 1)); return output; })); }
public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { return(new Func <UInt16, EncodeBuffer>(value => { return new EncodeBuffer(UnsignedVlq.Encode(value)); })); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { return(new Func <DecodeBuffer, UInt16>(input => { return (UInt16)UnsignedVlq.Decode(input); })); }
public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { // Get serializer for sub items var valueEncoder = recurse(type.GenericTypeArguments[0]); return(new Func <IList, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } // Serialize elements var output = new EncodeBuffer(); foreach (var element in value) { output.Append((EncodeBuffer)valueEncoder.DynamicInvokeTransparent(element)); } // Encode length output.SetFirst(UnsignedVlq.Encode((UInt64)value.Count + 1)); return output; })); }
public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { // Get serializer for sub items var valueEncoder = recurse(type.GetElementType()); return(new Func <Array, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } // Serialize elements var output = new EncodeBuffer(); foreach (var subValue in value) { output.Append((EncodeBuffer)valueEncoder.DynamicInvokeTransparent(subValue)); } // Encode length output.SetFirst(UnsignedVlq.Encode((UInt64)value.Length + 1)); // Number of elements, not number of bytes return output; })); }
public override EncodeBuffer Encode(Object value) { var v = value as String; if (v == null) { if (IsNullable) { return(Precomputed.Zero); } else { throw new UnexpectedNullValueException(); } } var length = (UInt64)v.Length; if (IsNullable) { length++; } // Encode value var output = new EncodeBuffer(2); output.Append(new ArraySegment <Byte>(Encoding.UTF8.GetBytes(v))); // Prepend length output.SetFirst(UnsignedVlq.Encode(length)); // Offset by one, since 0 is NULL return(output); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { // Get deserializer for sub items var valueDecoder = recurse(type.GenericTypeArguments[0]); return(new Func <DecodeBuffer, IList>(input => { // Read header var header = UnsignedVlq.Decode(input); // Handle nulls if (header == 0) { return null; } // Determine length var count = (Int32)header - 1; // Instantiate list var output = (IList)Activator.CreateInstance(type); //typeof(List<>).MakeGenericType(type.GenericTypeArguments) // Deserialize until we reach length limit for (var i = 0; i < count; i++) { // Deserialize element var element = valueDecoder.DynamicInvokeTransparent(input); // Add to output output.Add(element); } return output; })); }
public void UnsignedEncodeNullableNull() { var coder = new HeliumIntegerUnsigned(0, true, 1, 0); coder.Prepare(typeof(UInt32?)); var encoded = coder.Encode((UInt32?)null); Assert.Equal(UnsignedVlq.Encode(UnsignedVlq.MinValue).ToHexString(), encoded.ToHexString()); }
public void UnsignedEncodeMax() { var coder = new HeliumIntegerUnsigned(0, false, 1, 0); coder.Prepare(typeof(UInt64)); var encoded = coder.Encode(UnsignedVlq.MaxValue); Assert.Equal(UnsignedVlq.Encode(UnsignedVlq.MaxValue).ToHexString(), encoded.ToHexString()); }
public void UnsignedDecodeNullableNull() { var coder = new HeliumIntegerUnsigned(0, true, 1, 0); coder.Prepare(typeof(UInt32?)); var decoded = coder.Decode(new DecodeBuffer(UnsignedVlq.Encode(0).ToArray())); Assert.Equal((UInt32?)null, decoded); }
public void UnsignedDecodeMax() { var coder = new HeliumIntegerUnsigned(0, false, 1, 0); coder.Prepare(typeof(UInt64)); var decoded = coder.Decode(new DecodeBuffer(UnsignedVlq.Encode(UnsignedVlq.MaxValue).ToArray())); Assert.Equal(UnsignedVlq.MaxValue, decoded); }
public void UnsignedDecodeMin() { var coder = new HeliumIntegerUnsigned(0, false, 1, 0); coder.Prepare(typeof(UInt32)); var decoded = coder.Decode(new DecodeBuffer(UnsignedVlq.Encode(0).ToArray())); Assert.Equal((UInt32)0, decoded); }
public override Object Decode(DecodeBuffer input) { var v = UnsignedVlq.Decode(input); if (IsNullable) { if (v == 0) { return(null); } v--; } v *= Increment; v += Minimum; return(Convert.ChangeType(v, UnderlyingType)); }
public override EncodeBuffer Encode(Object value) { if (value == null && IsNullable) { return(Precomputed.Zero); } var v = Convert.ToUInt64(value); v -= Minimum; v /= Increment; if (IsNullable) { v++; } return(new EncodeBuffer(UnsignedVlq.Encode(v))); }
public override Object Decode(DecodeBuffer input) { // Decode header var header = UnsignedVlq.Decode(input); // Handle nulls if (IsNullable) { if (header == 0) { return(null); } header--; } // Decode value return(Encoding.UTF8.GetString(input.Underlying, input.GetIncrementOffset((Int32)header), (Int32)header)); }
public override EncodeBuffer Encode(Object value) { #if DEBUG if (null == Records) { throw new InvalidOperationException("Coder has not yet been prepared."); } #endif // Handle nulls if (null == value) { if (!IsNullable) { throw new UnexpectedNullValueException(); } return(Precomputed.Zero); } var output = new EncodeBuffer(); for (Byte i = 0; i < Records.Length; i++) { var record = Records[i]; // Extract value var v = record.Field.GetValue(value); // Add to output output.Append(record.Coder.Encode(v)); } // Increment length if nullable, to allow space for null representation var length = (UInt64)output.TotalLength; if (IsNullable) { length++; } // Encode length output.SetFirst(UnsignedVlq.Encode(length)); return(output); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { return(new Func <DecodeBuffer, String>(input => { // Decode header var header = UnsignedVlq.Decode(input); // Handle nulls if (header == 0) { return null; } // Determine length var length = (Int32)header - 1; // Decode value return Encoding.UTF8.GetString(input.Underlying, input.GetIncrementOffset(length), length); })); }
public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { return(new Func <String, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } // Encode value var output = new EncodeBuffer(2); output.Append(new ArraySegment <Byte>(Encoding.UTF8.GetBytes(value))); // Prepend length output.SetFirst(UnsignedVlq.Encode((UInt64)output.TotalLength + 1)); // Offset by one, since 0 is NULL return output; })); }
public override Object Decode(DecodeBuffer input) { #if DEBUG if (null == Records) { throw new InvalidOperationException("Coder has not yet been prepared."); } #endif // Read the length header var header = (Int32)UnsignedVlq.Decode(input); // Handle nulls if (IsNullable) { if (header == 0) { return(null); } header--; } // Instantiate output var output = Activator.CreateInstance(UnderlyingType); // Extract an inner buffer so that if fields are added to the class in the future we ignore them, being backwards compatible var innerInput = input.Extract(header); // Isolate bytes for body foreach (var record in Records) { // Deserialize value var v = record.Coder.Decode(innerInput); // Set it on property record.Field.SetValue(output, v); } return(output); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { // Get deserializer for sub items var keyDecoder = recurse(type.GenericTypeArguments[0]); var valueDecoder = recurse(type.GenericTypeArguments[1]); return(new Func <DecodeBuffer, IDictionary>(input => { // Read header var header = UnsignedVlq.Decode(input); if (header == 0) { return null; } // Get count var count = (Int32)header - 1; // Instantiate dictionary var output = (IDictionary)Activator.CreateInstance(type); // Loop through input buffer until depleted for (var i = 0; i < count; i++) { // Deserialize key var keyValue = keyDecoder.DynamicInvokeTransparent(input); // Deserialize value var valueValue = valueDecoder.DynamicInvokeTransparent(input); // Add to output output[keyValue] = valueValue; } return output; })); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { // Get deserializer for sub items var valueDecoder = recurse(type.GetElementType()); return(new Func <DecodeBuffer, Array>(input => { var header = UnsignedVlq.Decode(input); if (header == 0) { return null; } // Determine length var length = (Int32)header - 1; // Instantiate list var container = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(type.GetElementType())); // Deserialize until we reach length limit for (var i = 0; i < length; i++) { // Deserialize element var element = valueDecoder.DynamicInvokeTransparent(input); // Add to output container.Add(element); } // Convert to array and return var output = Array.CreateInstance(type.GetElementType(), container.Count); container.CopyTo(output, 0); return output; })); }
public void BooleanSerializeFalse() { Assert.Equal(UnsignedVlq.Encode(0), LightWeight.Serialize(false)); }
public void BooleanSerializeTrue() { Assert.Equal(UnsignedVlq.Encode(1), LightWeight.Serialize(true)); }
public Delegate GenerateEncoder(Type type, Func <Type, Delegate> recurse) { var records = new Record[Byte.MaxValue]; // Find all properties decorated with LightWeightProperty attribute var fieldCount = -1; foreach (var property in type.GetRuntimeFields()) { // Get property attribute which tells us the properties' index var attribute = (LightWeightPropertyAttribute)property.GetCustomAttribute(typeof(LightWeightPropertyAttribute), false); if (null == attribute) { // No attribute found, skip continue; } // Check for duplicate index if (null != records[attribute.Index]) { throw new DuplicateIndexException($"The index {attribute.Index} is already used and cannot be reused."); } // Note the max index used if (attribute.Index > fieldCount) { fieldCount = attribute.Index; } // Find/create encoder var encoder = recurse(property.FieldType); // Find floor, if any var transformations = property.GetCustomAttributes <TransformationAttribute>(true).ToArray(); // Store property in lookup records[attribute.Index] = new Record() { Field = property, Coder = encoder, Transformations = transformations }; } // If no properties, shortcut the whole thing and return a blank if (fieldCount == -1) { return(new Func <Object, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } return One; })); } // Check that no indexes have been missed for (var i = 0; i < fieldCount; i++) { if (null == records[i]) { throw new MissingIndexException($"Indexes must not be skipped, however missing index {i}."); // TODO: Make so indexes can be skipped for easier versioning } } return(new Func <Object, EncodeBuffer>(value => { // Handle nulls if (null == value) { return Null; } var output = new EncodeBuffer(); for (Byte i = 0; i <= fieldCount; i++) { var record = records[i]; // Get the serializer for the sub-item var subType = recurse(record.Field.FieldType); // Get it's method info var subMethodInfo = subType.GetMethodInfo(); // Extract value var v = record.Field.GetValue(value); // Apply transformations foreach (var transformation in record.Transformations) { v = transformation.ApplyEffect(v); } // Add to output output.Append((EncodeBuffer)record.Coder.DynamicInvokeTransparent(v)); } // Encode length output.SetFirst(UnsignedVlq.Encode((UInt64)output.TotalLength + 1)); // Number of bytes return output; })); }
public Delegate GenerateDecoder(Type type, Func <Type, Delegate> recurse) { var records = new Record[Byte.MaxValue]; // Find all properties decorated with LightWeightProperty attribute var maxIndex = -1; foreach (var property in type.GetRuntimeFields()) { // Get property attribute which tells us the properties' index var attribute = (LightWeightPropertyAttribute)property.GetCustomAttribute(typeof(LightWeightPropertyAttribute), false); if (null == attribute) { // No attribute found, skip continue; } // Check for duplicate index if (null != records[attribute.Index]) { throw new DuplicateIndexException($"The index {attribute.Index} is already used and cannot be reused."); } // Note the max index used if (attribute.Index > maxIndex) { maxIndex = attribute.Index; } // Find/create encoder var decoder = recurse(property.FieldType); // Find floor, if any var transformations = property.GetCustomAttributes <TransformationAttribute>(true).ToArray(); // Store property in lookup records[attribute.Index] = new Record() { Field = property, Coder = decoder, Transformations = transformations }; } // Check that no indexes have been missed for (var i = 0; i < maxIndex; i++) { if (null == records[i]) { throw new MissingIndexException($"Indexes must not be skipped, however missing index {i}."); } } return(new Func <DecodeBuffer, Object>(input => { // Read the length header var header = (Int32)UnsignedVlq.Decode(input); // Handle nulls if (header == 0) { return null; } // Determine length var length = header - 1; // Instantiate output var output = Activator.CreateInstance(type); // Extract an inner buffer so that if fields are added to the class in the future we ignore them, being backwards compatible var innerInput = input.Extract(length); // Isolate bytes for body for (var i = 0; i <= maxIndex; i++) { var record = records[i]; // Deserialize value var v = record.Coder.DynamicInvokeTransparent(innerInput); // Apply transformations foreach (var transformation in record.Transformations) { v = transformation.RemoveEffect(v); } // Set it on property record.Field.SetValue(output, v); } return output; })); }
public void UInt32DeserializeEnum() { Assert.Equal(TestEnum.B, LightWeight.Deserialize <TestEnum>(UnsignedVlq.Encode((UInt32)TestEnum.B).ToArray())); }
public void UInt32DeserializeMax() { Assert.Equal(UInt32.MaxValue, LightWeight.Deserialize <UInt32>(UnsignedVlq.Encode(UInt32.MaxValue).ToArray())); }
public void UInt32SerializeEnum() { Assert.Equal(UnsignedVlq.Encode((UInt32)TestEnum.B), LightWeight.Serialize(TestEnum.B)); }
public void UInt32SerializeMax() { Assert.Equal(UnsignedVlq.Encode(UInt32.MaxValue), LightWeight.Serialize(UInt32.MaxValue)); }
public void BooleanDeserializeFalse() { Assert.False(LightWeight.Deserialize <Boolean>(UnsignedVlq.Encode(0).ToArray())); }