diff --git a/Capnp.Net.Runtime.Tests/DeserializationTests.cs b/Capnp.Net.Runtime.Tests/DeserializationTests.cs index 647799b..5d543bb 100644 --- a/Capnp.Net.Runtime.Tests/DeserializationTests.cs +++ b/Capnp.Net.Runtime.Tests/DeserializationTests.cs @@ -1,4 +1,7 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Capnproto_test.Capnp.Test; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Linq; namespace Capnp.Net.Runtime.Tests { @@ -354,5 +357,40 @@ namespace Capnp.Net.Runtime.Tests Assert.AreEqual(double.NegativeInfinity, asListOfDoubles[0]); Assert.AreEqual(double.MaxValue, asListOfDoubles[1]); } + + [TestMethod] + public void NestedLists() + { + var expected = new int[][] { + new int[] { 1, 2, 3 }, + new int[] { 4, 5 }, + new int[] { 6 } }; + + var b = MessageBuilder.Create(); + var dss = b.CreateObject(); + dss.SetObject(expected); + DeserializerState d = dss; + var ld = d.RequireList(); + var result = ld.Cast2D(); + Assert.AreEqual(3, result.Count); + for (int i = 0; i < result.Count; i++) + { + CollectionAssert.AreEqual(expected[i], result[i].ToArray()); + } + + Assert.ThrowsException(() => ld.Cast2D()); + } + + [TestMethod] + public void LinearListWrongUse() + { + var b = MessageBuilder.Create(); + var dss = b.CreateObject(); + dss.SetObject(new int[] { 1, 2, 3 }); + DeserializerState d = dss; + var ld = d.RequireList(); + Assert.ThrowsException(() => ld.CastList()); + Assert.ThrowsException(() => ld.CastCapList()); + } } } diff --git a/Capnp.Net.Runtime.Tests/SerializationTests.cs b/Capnp.Net.Runtime.Tests/SerializationTests.cs index f719dc6..153feb8 100644 --- a/Capnp.Net.Runtime.Tests/SerializationTests.cs +++ b/Capnp.Net.Runtime.Tests/SerializationTests.cs @@ -79,6 +79,8 @@ namespace Capnp.Net.Runtime.Tests Assert.ThrowsException(() => { list[0] = null; }); list.Init(5); Assert.ThrowsException(() => list.Init(1)); + Assert.ThrowsException(() => { var _ = list[5]; }); + Assert.ThrowsException(() => { list[-1] = null; }); var c1 = new Counters(); var cap1 = new TestInterfaceImpl(c1); var c2 = new Counters(); @@ -152,6 +154,8 @@ namespace Capnp.Net.Runtime.Tests list.Init(7); Assert.ThrowsException(() => list.Init(1)); Assert.AreEqual(7, list.Count); + Assert.ThrowsException(() => { var _ = list[-1]; }); + Assert.ThrowsException(() => { list[7] = null; }); var c1 = new Counters(); var cap1 = new TestInterfaceImpl(c1); var obj1 = b.CreateObject(); @@ -234,6 +238,7 @@ namespace Capnp.Net.Runtime.Tests list.Init(4); Assert.ThrowsException(() => list.Init(1)); Assert.AreEqual(4, list.Count); + Assert.ThrowsException(() => { var _ = list[5]; }); list[0].SomeText = "0"; list[1].SomeText = "1"; list[2].SomeText = "2"; @@ -265,6 +270,8 @@ namespace Capnp.Net.Runtime.Tests list.Init(4); Assert.ThrowsException(() => list.Init(1)); Assert.AreEqual(4, list.Count); + Assert.ThrowsException(() => { var _ = list[5]; }); + Assert.ThrowsException(() => { list[-1] = null; }); list[0] = "0"; list[2] = null; list[3] = "3"; @@ -724,5 +731,15 @@ namespace Capnp.Net.Runtime.Tests DeserializerState d2 = dss; CollectionAssert.AreEqual(expected, d2.RequireList().CastText2().ToArray()); } + + [TestMethod] + public void EmptyListContract() + { + var list = new EmptyList(); + Assert.AreEqual(0, list.Count); + Assert.ThrowsException(() => { var _ = list[-1]; }); + Assert.ThrowsException(() => { var _ = list[0]; }); + Assert.AreEqual(0, list.ToArray().Length); + } } } diff --git a/Capnp.Net.Runtime/EmptyList.cs b/Capnp.Net.Runtime/EmptyList.cs index 0c1ebc6..c719551 100644 --- a/Capnp.Net.Runtime/EmptyList.cs +++ b/Capnp.Net.Runtime/EmptyList.cs @@ -8,14 +8,14 @@ namespace Capnp /// /// Implements an empty . /// - /// + /// list element type public class EmptyList : IReadOnlyList { /// - /// Always throws an . + /// Always throws an . /// /// Ignored - public T this[int index] => throw new ArgumentOutOfRangeException(nameof(index)); + public T this[int index] => throw new IndexOutOfRangeException(nameof(index)); /// /// Always 0. diff --git a/Capnp.Net.Runtime/ListDeserializer.cs b/Capnp.Net.Runtime/ListDeserializer.cs index 6d28ab9..e8499a6 100644 --- a/Capnp.Net.Runtime/ListDeserializer.cs +++ b/Capnp.Net.Runtime/ListDeserializer.cs @@ -11,6 +11,9 @@ namespace Capnp static class GenericCasts { public static Func? CastFunc; + + public static Func GetCastFunc() => CastFunc ?? + throw new NotSupportedException("Requested cast is not supported"); } static ListDeserializer() @@ -45,12 +48,7 @@ namespace Capnp T Cast() { - var func = GenericCasts.CastFunc; - - if (func == null) - throw new NotSupportedException("Requested cast is not supported"); - - return func(this); + return GenericCasts.GetCastFunc()(this); } /// @@ -91,7 +89,7 @@ namespace Capnp /// If does not qualify as capability interface. public virtual IReadOnlyList CastCapList() where T: class { - throw new NotSupportedException("This kind of list does not contain nested lists"); + throw new NotSupportedException("This kind of list cannot be represented as list of capabilities"); } object CastND(int n, Func func) @@ -158,6 +156,7 @@ namespace Capnp /// If this list cannot be represented in the desired manner. public IReadOnlyList> Cast2D() { + GenericCasts>.GetCastFunc(); // Probe to avoid lazy NotSupportedException return CastList().LazyListSelect(ld => ld.Cast>()); } diff --git a/Capnp.Net.Runtime/ListOfBitsSerializer.cs b/Capnp.Net.Runtime/ListOfBitsSerializer.cs index 2e5a94f..3e90aa8 100644 --- a/Capnp.Net.Runtime/ListOfBitsSerializer.cs +++ b/Capnp.Net.Runtime/ListOfBitsSerializer.cs @@ -11,35 +11,6 @@ namespace Capnp /// public class ListOfBitsSerializer: SerializerState, IReadOnlyList { - class Enumerator : IEnumerator - { - readonly ListOfBitsSerializer _self; - int _pos = -1; - - public Enumerator(ListOfBitsSerializer self) - { - _self = self; - } - - public bool Current => _pos >= 0 && _pos < _self.Count ? _self[_pos] : false; - - object IEnumerator.Current => Current; - - public void Dispose() - { - } - - public bool MoveNext() - { - return ++_pos < _self.Count; - } - - public void Reset() - { - _pos = -1; - } - } - /// /// Gets or sets the element at given index. /// @@ -121,10 +92,16 @@ namespace Capnp } } + IEnumerable Enumerate() + { + for (int i = 0; i < Count; i++) + yield return this[i]; + } + /// /// Implements /// - public IEnumerator GetEnumerator() => new Enumerator(this); + public IEnumerator GetEnumerator() => Enumerate().GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }