diff --git a/RDMSharp/Metadata/DataTree.cs b/RDMSharp/Metadata/DataTree.cs index e3fbca2..f32f04a 100644 --- a/RDMSharp/Metadata/DataTree.cs +++ b/RDMSharp/Metadata/DataTree.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace RDMSharp.Metadata { @@ -53,8 +54,27 @@ public bool Equals(DataTree other) return Name == other.Name && Index == other.Index && EqualityComparer.Default.Equals(Value, other.Value) && - EqualityComparer.Default.Equals(Children, other.Children) && - EqualityComparer.Default.Equals(Issues, other.Issues); + compairArrays(this, other); + + bool compairArrays(DataTree _this, DataTree other) + { + if (_this.Children != null) + { + if (!_this.Children.SequenceEqual(other.Children)) + return false; + } + else if (other.Children != null) + return false; + if (_this.Issues != null) + { + if (!_this.Issues.SequenceEqual(other.Issues)) + return false; + } + else if (other.Issues != null) + return false; + + return true; + } } public override int GetHashCode() diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs index 777c4d0..b295b2d 100644 --- a/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs @@ -2,50 +2,27 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Text.Json.Serialization; namespace RDMSharp.Metadata.JSON.OneOfTypes { public class BitFieldType : CommonPropertiesForNamed { - [JsonConstructor] - public BitFieldType(string name, - string displayName, - string notes, - string[] resources, - string type, - ushort size, - bool? valueForUnspecified, - BitType[] bits) : base() - { - if (!"bitField".Equals(type)) - throw new ArgumentException($"Argument {nameof(type)} has to be \"bitField\""); - if (size % 8 != 0) - throw new ArgumentOutOfRangeException($"Argument {nameof(size)} has to be a multiple of 8"); - - Name = name; - DisplayName = displayName; - Notes = notes; - Resources = resources; - Type = type; - Size = size; - ValueForUnspecified = valueForUnspecified; - Bits = bits; - } - [JsonPropertyName("name")] [JsonPropertyOrder(1)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override string Name { get; } + [JsonPropertyName("displayName")] [JsonPropertyOrder(2)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string DisplayName { get; } + [JsonPropertyName("notes")] [JsonPropertyOrder(4)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string Notes { get; } + [JsonPropertyName("resources")] [JsonPropertyOrder(5)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -63,11 +40,40 @@ public BitFieldType(string name, [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyOrder(32)] public bool? ValueForUnspecified { get; } + [JsonPropertyName("bits")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyOrder(41)] public BitType[] Bits { get; } + [JsonConstructor] + public BitFieldType(string name, + string displayName, + string notes, + string[] resources, + string type, + ushort size, + bool? valueForUnspecified, + BitType[] bits) : base() + { + if (!"bitField".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"bitField\""); + if (size % 8 != 0) + throw new ArgumentOutOfRangeException($"Argument {nameof(size)} has to be a multiple of 8"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Size = size; + ValueForUnspecified = valueForUnspecified; + Bits = bits; + } + public BitFieldType(string name, ushort size, BitType[] bits) : this(name, null, null, null, "bitField", size, null, bits) + { + } + public override PDL GetDataLength() { return new PDL((uint)(Size / 8)); @@ -94,10 +100,10 @@ public override byte[] ParsePayloadToData(DataTree dataTree) BitType bit = Bits.FirstOrDefault(b=>b.Name== bitDataTree.Name); if (bit == null) throw new ArithmeticException($"Can't find matching BitType {bitDataTree.Name}"); - if (bitDataTree.Index != bit.Index) + if (Bits[bitDataTree.Index] != bit) throw new ArithmeticException($"The given DataTree {nameof(bitDataTree.Index)}({bitDataTree.Index}) not match BitType {nameof(bit.Index)}({bit.Index})"); if (bitDataTree.Value is not bool value) - throw new ArithmeticException($"DataTree VAlue is not bool"); + throw new ArithmeticException($"DataTree Value is not bool"); data[bit.Index] = value; } @@ -110,15 +116,19 @@ public override DataTree ParseDataToPayload(ref byte[] data) List issueList = new List(); int byteCount = (Size / 8); if (byteCount != data.Length) + { issueList.Add(new DataTreeIssue($"Data length not match given Size/8 ({byteCount})")); - + byte[] cloneData = new byte[byteCount]; + Array.Copy(data, cloneData, data.Length); + data = cloneData; + } bool[] bools = Tools.DataToBoolArray(ref data, this.Size); - foreach (BitType bitType in Bits) - bitDataTrees.Add(new DataTree(bitType.Name, bitType.Index, bools[bitType.Index])); - - data = data.Skip(byteCount).ToArray(); - - return new DataTree(this.Name, 0, bitDataTrees.OrderBy(b=>b.Index), issueList.Count != 0 ? issueList.ToArray() : null); + for (uint i = 0; i < Bits.Length; i++) + { + BitType bitType = Bits[i]; + bitDataTrees.Add(new DataTree(bitType.Name, i, bools[bitType.Index])); + } + return new DataTree(this.Name, 0, children: bitDataTrees.OrderBy(b=>b.Index).ToArray(), issueList.Count != 0 ? issueList.ToArray() : null); } } -} +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs index fb0b65f..82520bf 100644 --- a/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs @@ -24,9 +24,12 @@ public BitType(string name, Index = index; Reserved = reserved; ValueIfReserved = valueIfReserved; + } + public BitType(string name, ushort index) : this(name, null, null, null, "bit", index, null, null) + { } - [JsonPropertyName("name")] + [JsonPropertyName("name")] [JsonPropertyOrder(1)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override string Name { get; } diff --git a/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs b/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs index a5752ee..5fd30cd 100644 --- a/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs +++ b/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs @@ -1,3 +1,4 @@ +using RDMSharp.Metadata; using RDMSharp.Metadata.JSON.OneOfTypes; using RDMSharp.RDM; @@ -23,6 +24,45 @@ public void TestMany() Assert.Throws(typeof(ArgumentException), () => bitFieldType = new BitFieldType("NAME", "DISPLAY_NAME", "NOTES", null, "botField", 16, false, bitTypes)); Assert.Throws(typeof(ArgumentOutOfRangeException), () => bitFieldType = new BitFieldType("NAME", "DISPLAY_NAME", "NOTES", null, "bitField", 7, false, bitTypes)); + + + bitTypes = new BitType[3]; + bitTypes[0] = new BitType("NAME11", 2); + bitTypes[1] = new BitType("NAME22", 4); + bitTypes[2] = new BitType("NAME33", 15); + bitFieldType = new BitFieldType("NAME_BIT_FIELD", 16, bitTypes); + var dataTree= new DataTree(bitFieldType.Name,0,new DataTree[] { new DataTree(bitTypes[0].Name, 0, true), new DataTree(bitTypes[1].Name, 1, true), new DataTree(bitTypes[2].Name, 2, true), }); + + DoParseDataTest(bitFieldType, dataTree, new byte[] { 0b00010100, 0b10000000 }); + } + private void DoParseDataTest(BitFieldType bitFieldType, DataTree dataTree, byte[] expectedData, string message = null) + { + Assert.Multiple(() => + { + Assert.That(dataTree.Value, Is.Null); + Assert.That(dataTree.Children, Is.Not.Null); + var data = new byte[0]; + Assert.DoesNotThrow(() => data = bitFieldType.ParsePayloadToData(dataTree), message); + Assert.That(data, Is.EqualTo(expectedData), message); + + byte[] clonaData = new byte[data.Length]; + Array.Copy(data, clonaData, clonaData.Length); + var parsedDataTree = bitFieldType.ParseDataToPayload(ref clonaData); + Assert.That(clonaData, Has.Length.EqualTo(0), message); + + Assert.That(parsedDataTree, Is.EqualTo(dataTree), message); + Assert.That(parsedDataTree.Value, Is.Null); + + //Test for short Data & PDL Issue + clonaData = new byte[data.Length - 1]; + Array.Copy(data, clonaData, clonaData.Length); + Assert.DoesNotThrow(() => parsedDataTree = bitFieldType.ParseDataToPayload(ref clonaData)); + Assert.That(parsedDataTree.Issues, Is.Not.Null); + Assert.That(parsedDataTree.Value, Is.Null); + Assert.That(parsedDataTree.Children, Is.Not.Null); + + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree("Different Name", dataTree.Index, dataTree.Value)), message); + }); } } } \ No newline at end of file