Skip to content

Commit

Permalink
Merge branch 'develop' into 'master'
Browse files Browse the repository at this point in the history
Develop

See merge request company-projects/Meadow!55
  • Loading branch information
zone117x committed Oct 19, 2018
2 parents 73ed06b + f515619 commit 635bf12
Show file tree
Hide file tree
Showing 28 changed files with 671 additions and 159 deletions.
51 changes: 51 additions & 0 deletions src/Meadow.Core.Test/AbiPacked.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,56 @@ public void MultipleMixedTypes()
Assert.Equal(expectedOutput, resultHex);
}

[Fact]
public void MultiDimensionalArrayEncoding()
{
var exampleArray = ArrayExtensions.CreateJaggedArray<UInt256[][][]>(2, 6, 3);
exampleArray[0][0][0] = 3;
exampleArray[0][4][2] = 3333;
exampleArray[0][2][1] = 777;

var encoded = SolidityUtil.AbiEncode("uint256[2][6][3]", exampleArray);
var encodedHex = encoded.ToHexString();
var recode = SolidityUtil.AbiDecode<UInt256[][][]>("uint256[2][6][3]", encoded);

Assert.Equal(exampleArray[0][0][0], recode[0][0][0]);
Assert.Equal(exampleArray[0][4][2], recode[0][4][2]);
Assert.Equal(exampleArray[0][2][1], recode[0][2][1]);
}

[Fact]
public void NonGenericArrayEncoding()
{
var exampleArray = new List<UInt256>();
exampleArray.Add(3);
exampleArray.Add(777);
exampleArray.Add(3333);

var encoded = SolidityUtil.AbiEncode("uint256[3]", exampleArray);
var encodedHex = encoded.ToHexString();
var recode = SolidityUtil.AbiDecode<UInt256[]>("uint256[3]", encoded);

Assert.Equal(exampleArray[0], recode[0]);
Assert.Equal(exampleArray[1], recode[1]);
Assert.Equal(exampleArray[2], recode[2]);
}

[Fact]
public void NonGenericArrayEncoding2()
{
var exampleArray = new List<List<UInt256>>();
exampleArray.Add(new List<UInt256> { 1, 2, 3 });
exampleArray.Add(new List<UInt256> { 4, 5, 6 });
exampleArray.Add(new List<UInt256> { 7, 8, 9 });
exampleArray.Add(new List<UInt256> { 10, 11, 12 });

var encoded = SolidityUtil.AbiEncode("uint256[4][3]", exampleArray);
var encodedHex = encoded.ToHexString();
var recode = SolidityUtil.AbiDecode<UInt256[][]>("uint256[4][3]", encoded);

Assert.Equal(exampleArray[0][0], recode[0][0]);
Assert.Equal(exampleArray[1][0], recode[1][0]);
Assert.Equal(exampleArray[2][0], recode[2][0]);
}
}
}
8 changes: 7 additions & 1 deletion src/Meadow.Core/AbiEncoding/AbiDecodeBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ public AbiDecodeBuffer(ReadOnlySpan<byte> span, params AbiTypeInfo[] typeInfo)
switch (t.Category)
{
case SolidityTypeCategory.FixedArray:
headLength += UInt256.SIZE * t.ArrayLength;
int totalArraySize = 1;
foreach (var dim in t.ArrayDimensionSizes)
{
totalArraySize *= dim;
}

headLength += UInt256.SIZE * totalArraySize;
break;
default:
headLength += UInt256.SIZE;
Expand Down
8 changes: 7 additions & 1 deletion src/Meadow.Core/AbiEncoding/AbiEncodeBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ public AbiEncodeBuffer(Span<byte> span, params AbiTypeInfo[] typeInfo)
switch (t.Category)
{
case SolidityTypeCategory.FixedArray:
HeadLength += UInt256.SIZE * t.ArrayLength;
int totalArraySize = 1;
foreach (var dim in t.ArrayDimensionSizes)
{
totalArraySize *= dim;
}

HeadLength += UInt256.SIZE * totalArraySize;
break;
default:
HeadLength += UInt256.SIZE;
Expand Down
16 changes: 3 additions & 13 deletions src/Meadow.Core/AbiEncoding/AbiTypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ public class AbiTypeInfo : IEquatable<AbiTypeInfo>
/// </summary>
public readonly int PrimitiveTypeByteSize;

/// <summary>
/// The length of static sized array types, for dynamic arrays this is zero.
/// For non-array types this is zero.
/// </summary>
public readonly int ArrayLength;

public readonly SolidityTypeCategory Category;

public readonly SolidityTypeElementaryBase ElementaryBaseType = SolidityTypeElementaryBase.None;
Expand All @@ -55,9 +49,6 @@ public class AbiTypeInfo : IEquatable<AbiTypeInfo>
Category == SolidityTypeCategory.Bytes ||
ElementaryBaseType == SolidityTypeElementaryBase.Bytes;

public bool IsMultiDimensionalArray =>
IsArrayType && (ArrayItemInfo.IsArrayType || ArrayItemInfo.IsSpecialBytesType);

public bool IsStaticType => Category == SolidityTypeCategory.Elementary;
public bool IsDynamicType => !IsStaticType;

Expand All @@ -71,22 +62,21 @@ public class AbiTypeInfo : IEquatable<AbiTypeInfo>
/// For example the type uint256[3][][6] would be represented as [3, 0, 6].
/// Null for non-multi-dimensional types.
/// </summary>
public readonly int[] MultiDimensionalArraySizes;
public readonly int[] ArrayDimensionSizes;

public AbiTypeInfo(string solidityName, Type clrType, int primitiveTypeByteSize,
SolidityTypeCategory category = SolidityTypeCategory.Elementary,
SolidityTypeElementaryBase elementaryBaseType = SolidityTypeElementaryBase.None,
int arrayTypeLength = 0, AbiTypeInfo arrayItemInfo = null, int[] arrayDimensionSizes = null)
AbiTypeInfo arrayItemInfo = null, int[] arrayDimensionSizes = null)
{
SolidityName = solidityName;
ClrType = clrType;
ClrTypeName = ClrType.FullName;
PrimitiveTypeByteSize = primitiveTypeByteSize;
Category = category;
ElementaryBaseType = elementaryBaseType;
ArrayLength = arrayTypeLength;
ArrayItemInfo = arrayItemInfo;
MultiDimensionalArraySizes = arrayDimensionSizes;
ArrayDimensionSizes = arrayDimensionSizes;
}

public static AbiTypeInfo Create(string solidityName)
Expand Down
16 changes: 9 additions & 7 deletions src/Meadow.Core/AbiEncoding/AbiTypeMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ static AbiTypeMap()
typeof(IEnumerable<byte>),
primitiveTypeByteSize: i,
SolidityTypeCategory.Elementary,
SolidityTypeElementaryBase.Bytes,
arrayTypeLength: i);
SolidityTypeElementaryBase.Bytes);
}

// signed and unsigned integer type of M bits, 0 < M <= 256, M % 8 == 0
Expand Down Expand Up @@ -118,10 +117,9 @@ public static AbiTypeInfo GetSolidityTypeInfo(string name)
}

var bracketPart = name.Substring(arrayBracket);
int arraySize = 0;
var typeCategory = SolidityTypeCategory.DynamicArray;

int[] arrayDimensionSizes = null;
int[] arrayDimensionSizes;

// if a fixed array length has been set, ex: uint64[10]
if (bracketPart.Length > 2)
Expand All @@ -131,24 +129,28 @@ public static AbiTypeInfo GetSolidityTypeInfo(string name)
arrayDimensionSizes = ParseArrayDimensionSizes(bracketPart);
if (arrayDimensionSizes[0] > 0)
{
arraySize = arrayDimensionSizes[0];
typeCategory = SolidityTypeCategory.FixedArray;
}
}
else
{
// parse the number within the square brackets
var sizeStr = bracketPart.Substring(1, bracketPart.Length - 2);
arraySize = int.Parse(sizeStr, CultureInfo.InvariantCulture);
var arraySize = int.Parse(sizeStr, CultureInfo.InvariantCulture);
arrayDimensionSizes = new[] { arraySize };
typeCategory = SolidityTypeCategory.FixedArray;
}
}
else
{
arrayDimensionSizes = new[] { 0 };
}

var baseName = name.Substring(0, arrayBracket);
if (_finiteTypes.TryGetValue(baseName, out var baseInfo))
{
var arrayType = typeof(IEnumerable<>).MakeGenericType(baseInfo.ClrType);
var info = new AbiTypeInfo(name, arrayType, baseInfo.PrimitiveTypeByteSize, typeCategory, SolidityTypeElementaryBase.None, arraySize, baseInfo, arrayDimensionSizes);
var info = new AbiTypeInfo(name, arrayType, baseInfo.PrimitiveTypeByteSize, typeCategory, SolidityTypeElementaryBase.None, baseInfo, arrayDimensionSizes);
_cachedTypes[name] = info;
return info;
}
Expand Down
46 changes: 15 additions & 31 deletions src/Meadow.Core/AbiEncoding/DecoderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,23 @@ namespace Meadow.Core.AbiEncoding
{
public static class DecoderFactory
{
public static DecodeDelegate<TItem[]> GetMultiDimArrayDecoder<TItem>(AbiTypeInfo solidityType)
public static DecodeDelegate<TItem> GetDecoder<TItem>(AbiTypeInfo solidityType)
{
IAbiTypeEncoder encoder;
IAbiTypeEncoder itemEncoder;

if (solidityType.ArrayItemInfo.ElementaryBaseType == SolidityTypeElementaryBase.Bytes)
{
itemEncoder = new BytesMEncoder();
}
else
{
// TODO: define all multi-dim array encoder runtime matches
throw new NotImplementedException();
}

itemEncoder.SetTypeInfo(solidityType.ArrayItemInfo);

switch (solidityType.Category)
{
case SolidityTypeCategory.DynamicArray:
encoder = new DynamicArrayEncoderNonGeneric(itemEncoder);
break;
case SolidityTypeCategory.FixedArray:
encoder = new FixedArrayEncoderNonGeneric(itemEncoder);
break;
default:
throw new ArgumentException($"Encoder factory for array types was called with a type '{solidityType.Category}'");
}

var encoder = EncoderFactory.LoadEncoder(solidityType);
encoder.SetTypeInfo(solidityType);

void Decode(AbiTypeInfo st, ref AbiDecodeBuffer buff, out TItem[] val)
void Decode(AbiTypeInfo st, ref AbiDecodeBuffer buff, out TItem val)
{
encoder.DecodeObject(ref buff, out var objectVal);
var objectArray = (object[])objectVal;
val = objectArray.Select(v => (TItem)v).ToArray();
val = (TItem)objectVal;
}

return Decode;
}

/// <summary>
/// Used for regular one-dimensional arrays
/// </summary>
public static DecodeDelegate<TItem[]> GetArrayDecoder<TItem>(IAbiTypeEncoder<TItem> itemEncoder)
{
void Decode(AbiTypeInfo solidityType, ref AbiDecodeBuffer buff, out TItem[] val)
Expand Down Expand Up @@ -134,6 +110,14 @@ public static void Decode(AbiTypeInfo solidityType, ref AbiDecodeBuffer buff, ou
}
}

public static void Decode<TItem>(AbiTypeInfo solidityType, ref AbiDecodeBuffer buff, out TItem val)
{
var encoder = EncoderFactory.LoadEncoder(solidityType);
encoder.SetTypeInfo(solidityType);
encoder.DecodeObject(ref buff, out var objectVal);
val = (TItem)objectVal;
}

public static void Decode(AbiTypeInfo solidityType, ref AbiDecodeBuffer buff, out string val)
{
var encoder = new StringEncoder();
Expand Down
59 changes: 58 additions & 1 deletion src/Meadow.Core/AbiEncoding/EncoderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,48 @@ public static IAbiTypeEncoder<IEnumerable<TItem>> LoadEncoder<TItem>(string soli
return encoder;
}

public static IAbiTypeEncoder<byte[]> LoadEncoder(string solidityType, in byte[] val)
{
var info = AbiTypeMap.GetSolidityTypeInfo(solidityType);
switch (info.Category)
{
case SolidityTypeCategory.Bytes:
{
var encoder = new BytesEncoder();
encoder.SetTypeInfo(info);
encoder.SetValue(val);
return encoder;
}

case SolidityTypeCategory.Elementary when info.ElementaryBaseType == SolidityTypeElementaryBase.Bytes:
{
var encoder = new BytesMEncoder();
encoder.SetTypeInfo(info);
encoder.SetValue(val);
return encoder;
}

case SolidityTypeCategory.DynamicArray:
{
var encoder = new DynamicArrayEncoder<byte>(new UInt8Encoder());
encoder.SetTypeInfo(info);
encoder.SetValue(val);
return encoder;
}

case SolidityTypeCategory.FixedArray:
{
var encoder = new FixedArrayEncoder<byte>(new UInt8Encoder());
encoder.SetTypeInfo(info);
encoder.SetValue(val);
return encoder;
}

default:
throw new ArgumentException($"Encoder factor method for byte arrays called with type '{info.Category}'");
}
}

public static IAbiTypeEncoder<IEnumerable<byte>> LoadEncoder(string solidityType, in IEnumerable<byte> val)
{
var info = AbiTypeMap.GetSolidityTypeInfo(solidityType);
Expand All @@ -91,6 +133,13 @@ public static IAbiTypeEncoder<IEnumerable<byte>> LoadEncoder(string solidityType
}

case SolidityTypeCategory.DynamicArray:
{
var encoder = new DynamicArrayEncoder<byte>(new UInt8Encoder());
encoder.SetTypeInfo(info);
encoder.SetValue(val);
return encoder;
}

case SolidityTypeCategory.FixedArray:
{
var encoder = new FixedArrayEncoder<byte>(new UInt8Encoder());
Expand Down Expand Up @@ -209,7 +258,7 @@ public static IAbiTypeEncoder<UInt256> LoadEncoder(string solidityType, in UInt2
return encoder;
}

public static IAbiTypeEncoder GetEncoder(AbiTypeInfo solidityType)
static IAbiTypeEncoder GetEncoder(AbiTypeInfo solidityType)
{
switch (solidityType.Category)
{
Expand Down Expand Up @@ -287,6 +336,14 @@ public static IAbiTypeEncoder LoadEncoder(AbiTypeInfo solidityType)
encoder.SetTypeInfo(solidityType);
return encoder;
}

public static IAbiTypeEncoder LoadEncoderNonGeneric(AbiTypeInfo solidityType, object val)
{
var encoder = GetEncoder(solidityType);
encoder.SetTypeInfo(solidityType);
encoder.SetValue(val);
return encoder;
}
}

}

0 comments on commit 635bf12

Please sign in to comment.