Skip to content

Commit

Permalink
Adapt BaseBitSeq class to handle Lsb0 and Msb0.Msb0.
Browse files Browse the repository at this point in the history
Also add BitArray to display bits
  • Loading branch information
Apolixit committed Sep 26, 2024
1 parent ecb2644 commit f0923a0
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 22 deletions.
101 changes: 90 additions & 11 deletions Substrate.NetApi.Test/TypeConverters/BaseTypesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,63 @@
using NUnit.Framework;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System.Collections;

namespace Substrate.NetApi.Test
{
public sealed class Lsb0 : BaseType
{

/// <inheritdoc/>
public override string TypeName()
{
return "Lsb0";
}

/// <inheritdoc/>
public override byte[] Encode()
{
var result = new List<byte>();
return result.ToArray();
}

/// <inheritdoc/>
public override void Decode(byte[] byteArray, ref int p)
{
var start = p;
var bytesLength = p - start;
TypeSize = bytesLength;
Bytes = new byte[bytesLength];
global::System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
}
}

public sealed class Msb0 : BaseType
{

/// <inheritdoc/>
public override string TypeName()
{
return "Msb0";
}

/// <inheritdoc/>
public override byte[] Encode()
{
var result = new List<byte>();
return result.ToArray();
}

/// <inheritdoc/>
public override void Decode(byte[] byteArray, ref int p)
{
var start = p;
var bytesLength = p - start;
TypeSize = bytesLength;
Bytes = new byte[bytesLength];
global::System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
}
}
public class BaseTypesTest
{
[Test]
Expand Down Expand Up @@ -187,28 +241,53 @@ public void BaseOptTest()
Assert.IsTrue(exceptionThrown, "Exception not thrown for explicit cast with OptionFlag = false");
}

[Test]
public void BaseBitSeq_DisplayTest()
{
var testCase1 = "0xa00b80050000";
var baseBitSeqLsb0_1 = new BaseBitSeq<U8, Lsb0>();
var baseBitSeqMsb0_1 = new BaseBitSeq<U8, Msb0>();
baseBitSeqLsb0_1.Create(testCase1);
baseBitSeqMsb0_1.Create(testCase1);

Assert.That(baseBitSeqLsb0_1.Encode(), Is.EquivalentTo(baseBitSeqMsb0_1.Encode()));
Assert.That(baseBitSeqLsb0_1.DisplayToBits(), Is.EqualTo("0b11010000_00000001_10100000_00000000_00000000"));
Assert.That(baseBitSeqMsb0_1.DisplayToBits(), Is.EqualTo("0b00001011_10000000_00000101_00000000_00000000"));

}

[Test]
public void BaseBitSeqTest()
{
var testCase1 = "0xa00b80050000";
var bitSeqTest1 = FromBitString("0b11010000_00000001_10100000_00000000_00000000");
var baseBitSeq1 = new BaseBitSeq<U8, U8>();
baseBitSeq1.Create(testCase1);
var bits = "0b11010000_00000001_10100000_00000000_00000000";
var bitSeqTest1 = FromBitString(bits);
var baseBitSeqLsb0_1 = new BaseBitSeq<U8, Lsb0>();
var baseBitSeqMsb0_1 = new BaseBitSeq<U8, Msb0>();
baseBitSeqLsb0_1.Create(testCase1);
baseBitSeqMsb0_1.Create(testCase1);
for (int i = 0; i < bitSeqTest1.Length; i++)
{
Assert.AreEqual(bitSeqTest1[i], baseBitSeq1.Value[i].Value);
Assert.AreEqual(bitSeqTest1[i], baseBitSeqLsb0_1.Value[i].Value);
}
Assert.AreEqual(testCase1, Utils.Bytes2HexString(baseBitSeq1.Encode()).ToLower());
Assert.AreEqual(testCase1, Utils.Bytes2HexString(baseBitSeqLsb0_1.Encode()).ToLower());

var baseBitSeq1_bits = new BaseBitSeq<U8, Lsb0>();
baseBitSeq1_bits.CreateFromBitString(bits);
Assert.That(testCase1, Is.EqualTo(Utils.Bytes2HexString(baseBitSeq1_bits.Encode()).ToLower()));

var baseBitSeqMsb0_bits = new BaseBitSeq<U8, Msb0>();
baseBitSeqMsb0_bits.CreateFromBitString(bits);
Assert.That(bits, Is.EqualTo(baseBitSeqMsb0_bits.DisplayToBits()));

// Let's create the same object but with the other Create() method
var baseBitSeq1_1 = new BaseBitSeq<U8, U8>();
baseBitSeq1_1.Create(baseBitSeq1.Value);
Assert.AreEqual(baseBitSeq1.Bytes, baseBitSeq1_1.Bytes);
Assert.AreEqual(baseBitSeq1.Value, baseBitSeq1_1.Value);
Assert.AreEqual(baseBitSeq1.TypeSize, baseBitSeq1_1.TypeSize);
var baseBitSeq1_1 = new BaseBitSeq<U8, Lsb0>();
baseBitSeq1_1.Create(baseBitSeqLsb0_1.Encode());
Assert.AreEqual(baseBitSeqLsb0_1.Bytes, baseBitSeq1_1.Bytes);
Assert.AreEqual(baseBitSeqLsb0_1.TypeSize, baseBitSeq1_1.TypeSize);

var bitSeqTest2 = FromBitString("0b10000010_10000010_00101000_00000000_00000000");
var baseBitSeq2 = new BaseBitSeq<U8, U8>();
var baseBitSeq2 = new BaseBitSeq<U8, Lsb0>();
baseBitSeq2.Create("0xa04141140000");
for (int i = 0; i < bitSeqTest1.Length; i++)
{
Expand Down
94 changes: 83 additions & 11 deletions Substrate.NetApi/Model/Types/Base/BaseBitSeq.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using Newtonsoft.Json;
using Substrate.NetApi.Model.Types.Primitive;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Substrate.NetApi.Model.Types.Base
{
Expand Down Expand Up @@ -31,19 +34,38 @@ public class BaseBitSeq<T1, T2> : IType
[JsonIgnore]
public byte[] Bytes { get; internal set; }

private BitArray _bits { get; set; }

/// <summary>
/// Return if it is LSB (Least Significant Bit first) or MSB (Most Significant Bit first)
/// </summary>
public bool IsLsb {
get
{
switch (typeof(T2).Name.ToLower())
{
case "lsb0":
return true;
case "msb0":
return false;
default:
return true; // not sure if I should throw an exception here or just assume lsb0 (which is the default)
}
}
}

/// <summary>
/// Encode to Bytes
/// </summary>
/// <returns></returns>
public byte[] Encode()
{
var result = new List<byte>
{
Reverse((byte)Value.Length)
};
var result = new List<byte>();
result.AddRange(new CompactInteger(Value.Length * 8).Encode());

for (int i = 0; i < Value.Length; i++)
{
result.AddRange(Reverse(Value[i].Encode()));
result.AddRange(IsLsb ? Reverse(Value[i].Encode()) : Value[i].Encode());
}
return result.ToArray();
}
Expand All @@ -56,16 +78,19 @@ public byte[] Encode()
public void Decode(byte[] byteArray, ref int p)
{
var start = p;

var length = Reverse(byteArray[0]);

p++;
int lengthInner = CompactInteger.Decode(byteArray, ref p);
var length = (int)Math.Ceiling((decimal)lengthInner / (decimal)8);
var tmpBytes = byteArray;
if (IsLsb)
{
tmpBytes = Reverse(byteArray);
}

var array = new T1[length];
for (var i = 0; i < length; i++)
{
var t = new T1();
t.Decode(Reverse(byteArray), ref p);
t.Decode(tmpBytes, ref p);
array[i] = t;
}

Expand All @@ -74,6 +99,9 @@ public void Decode(byte[] byteArray, ref int p)
Bytes = new byte[TypeSize];
Array.Copy(byteArray, start, Bytes, 0, TypeSize);
Value = array;

// By default, BitArray is using Lsb0. So we need to reverse the bits again
_bits = new BitArray(array.SelectMany(x => Reverse(x.Encode())).ToArray());
}

/// <summary>
Expand Down Expand Up @@ -104,6 +132,27 @@ public void Create(T1[] list)
/// <param name="str"></param>
public void CreateFromJson(string str) => Create(Utils.HexToByteArray(str));

/// <summary>
/// Create <see cref="BaseBitSeq{T1, T2}"/> from string bits
/// Example : CreateFromBitString("0b11010000_00000001_10100000_00000000_00000000")
/// </summary>
/// <param name="bits"></param>
public void CreateFromBitString(string bits)
{
var s = bits.Replace("0b", "").Split('_');

var result = new List<byte>();

for (int i = 0; i < s.Length; i++)
{
byte b = Convert.ToByte(s[i], 2);
result.Add(IsLsb ? Reverse(b) : b);
}

result.InsertRange(0, new CompactInteger(result.Count * 8).Encode());
Create(result.ToArray());
}

/// <summary>
/// Create from a byte array
/// </summary>
Expand All @@ -121,7 +170,30 @@ public void Create(byte[] byteArray)
public IType New() => this;

/// <inheritdoc/>
public override string ToString() => JsonConvert.SerializeObject(this);
public override string ToString() => $"{{ bits = {_bits.Count}, capacity = {_bits.Count}}} => [{DisplayToBits()}]";

/// <summary>
/// Display this instance to bits
/// </summary>
/// <returns></returns>
public string DisplayToBits()
{
var bitString = new System.Text.StringBuilder(_bits.Count);
bitString.Append("0b");
for(int i = 0; i < _bits.Length; i++)
{
bitString.Append(_bits[i] ? '1' : '0');

if ((i + 1) % 8 == 0 && i != _bits.Count - 1)
{
bitString.Append("_");
}
}

return bitString.ToString();
}

public int InternalLength => _bits.Length;

/// <summary>
/// Reverse
Expand Down

0 comments on commit f0923a0

Please sign in to comment.