Skip to content

Commit

Permalink
Allow to iterate a byte array inside the smart contract (neo-project#…
Browse files Browse the repository at this point in the history
…1281)

* Update changes

* Fix UT

* Rename

* Update ByteArrayWrapper.cs

* Support Neo.Iterator.Create

* Add ut and Rename

* Cover line

* Revert rename
  • Loading branch information
shargon authored and Tommo-L committed Jun 22, 2020
1 parent 284b593 commit 10e141c
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 7 deletions.
20 changes: 15 additions & 5 deletions src/neo/SmartContract/InteropService.NEO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,20 @@ private static bool Storage_Find(ApplicationEngine engine)

private static bool Enumerator_Create(ApplicationEngine engine)
{
if (engine.CurrentContext.EvaluationStack.Pop() is VMArray array)
IEnumerator enumerator;
switch (engine.CurrentContext.EvaluationStack.Pop())
{
IEnumerator enumerator = new ArrayWrapper(array);
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(enumerator));
return true;
case VMArray array:
enumerator = new ArrayWrapper(array);
break;
case PrimitiveType primitive:
enumerator = new ByteArrayWrapper(primitive);
break;
default:
return false;
}
return false;
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(enumerator));
return true;
}

private static bool Enumerator_Next(ApplicationEngine engine)
Expand Down Expand Up @@ -312,6 +319,9 @@ private static bool Iterator_Create(ApplicationEngine engine)
case Map map:
iterator = new MapWrapper(map);
break;
case PrimitiveType primitive:
iterator = new ByteArrayWrapper(primitive);
break;
default:
return false;
}
Expand Down
41 changes: 41 additions & 0 deletions src/neo/SmartContract/Iterators/ByteArrayWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Neo.VM.Types;
using System;

namespace Neo.SmartContract.Iterators
{
internal class ByteArrayWrapper : IIterator
{
private readonly byte[] array;
private int index = -1;

public ByteArrayWrapper(PrimitiveType value)
{
this.array = value.ToByteArray().ToArray();
}

public void Dispose() { }

public PrimitiveType Key()
{
if (index < 0)
throw new InvalidOperationException();
return index;
}

public bool Next()
{
int next = index + 1;
if (next >= array.Length)
return false;
index = next;
return true;
}

public StackItem Value()
{
if (index < 0)
throw new InvalidOperationException();
return new Integer(array[index]);
}
}
}
49 changes: 49 additions & 0 deletions tests/neo.UnitTests/SmartContract/Iterators/UT_PrimitiveWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.SmartContract.Iterators;
using Neo.VM;
using Neo.VM.Types;
using System;

namespace Neo.UnitTests.SmartContract.Iterators
{
[TestClass]
public class UT_PrimitiveWrapper
{
[TestMethod]
public void TestGeneratorAndDispose()
{
ByteArrayWrapper arrayWrapper = new ByteArrayWrapper(new ByteArray(new byte[0]));
Assert.IsNotNull(arrayWrapper);
Action action = () => arrayWrapper.Dispose();
action.Should().NotThrow<Exception>();
}

[TestMethod]
public void TestKeyAndValue()
{
ByteArrayWrapper arrayWrapper = new ByteArrayWrapper(new byte[] { 0x01, 0x02 });
Action action1 = () => arrayWrapper.Key();
action1.Should().Throw<InvalidOperationException>();
Action action2 = () => arrayWrapper.Value();
action2.Should().Throw<InvalidOperationException>();
arrayWrapper.Next();
Assert.AreEqual(0x00, arrayWrapper.Key().GetBigInteger());
Assert.AreEqual(0x01, arrayWrapper.Value());
arrayWrapper.Next();
Assert.AreEqual(0x01, arrayWrapper.Key().GetBigInteger());
Assert.AreEqual(0x02, arrayWrapper.Value());
}

[TestMethod]
public void TestNext()
{
ByteArrayWrapper arrayWrapper = new ByteArrayWrapper(new byte[] { 0x01, 0x02 });
Assert.AreEqual(true, arrayWrapper.Next());
Assert.AreEqual(0x01, arrayWrapper.Value());
Assert.AreEqual(true, arrayWrapper.Next());
Assert.AreEqual(0x02, arrayWrapper.Value());
Assert.AreEqual(false, arrayWrapper.Next());
}
}
}
8 changes: 6 additions & 2 deletions tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public void TestEnumerator_Create()
.Should().Be(new byte[] { 0x01 }.ToHexString());

engine.CurrentContext.EvaluationStack.Push(1);
InteropService.Invoke(engine, InteropService.Neo_Enumerator_Create).Should().BeFalse();
InteropService.Invoke(engine, InteropService.Neo_Enumerator_Create).Should().BeTrue();
}

[TestMethod]
Expand Down Expand Up @@ -380,6 +380,10 @@ public void TestIterator_Create()
ret.GetInterface<IIterator>().Value().GetSpan().ToHexString()
.Should().Be(new byte[] { 0x01 }.ToHexString());

var interop = new InteropInterface<object>(1);
engine.CurrentContext.EvaluationStack.Push(interop);
InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeFalse();

var map = new Map
{
{ new Integer(1), new Integer(2) },
Expand All @@ -393,7 +397,7 @@ public void TestIterator_Create()
ret.GetInterface<IIterator>().Value().GetBigInteger().Should().Be(2);

engine.CurrentContext.EvaluationStack.Push(1);
InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeFalse();
InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeTrue();
}

[TestMethod]
Expand Down

0 comments on commit 10e141c

Please sign in to comment.