Skip to content

Commit

Permalink
Add StackItem.ToJson() (neo-project#1569)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzhang authored and Tommo-L committed Jun 22, 2020
1 parent 9fd8a2a commit 1170143
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/neo/IO/ReferenceEqualityComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Neo.IO
{
internal sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer<object>
{
public static readonly ReferenceEqualityComparer Default = new ReferenceEqualityComparer();

private ReferenceEqualityComparer()
{
}

public new bool Equals(object x, object y)
{
return x == y;
}

public int GetHashCode(object obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
}
47 changes: 47 additions & 0 deletions src/neo/VM/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.IO.Json;
using Neo.SmartContract;
using Neo.VM.Types;
using System;
Expand Down Expand Up @@ -219,6 +220,52 @@ public static byte[] MakeScript(this UInt160 scriptHash, string operation, param
}
}

public static JObject ToJson(this StackItem item)
{
return ToJson(item, null);
}

private static JObject ToJson(StackItem item, HashSet<StackItem> context)
{
JObject json = new JObject();
json["type"] = item.Type;
switch (item)
{
case Array array:
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Default);
if (!context.Add(array)) throw new InvalidOperationException();
json["value"] = new JArray(array.Select(p => ToJson(p, context)));
break;
case Boolean boolean:
json["value"] = boolean.ToBoolean();
break;
case Buffer buffer:
json["value"] = Convert.ToBase64String(buffer.InnerBuffer);
break;
case ByteString byteString:
json["value"] = Convert.ToBase64String(byteString.Span);
break;
case Integer integer:
json["value"] = integer.ToBigInteger().ToString();
break;
case Map map:
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Default);
if (!context.Add(map)) throw new InvalidOperationException();
json["value"] = new JArray(map.Select(p =>
{
JObject item = new JObject();
item["key"] = ToJson(p.Key, context);
item["value"] = ToJson(p.Value, context);
return item;
}));
break;
case Pointer pointer:
json["value"] = pointer.Position;
break;
}
return json;
}

public static ContractParameter ToParameter(this StackItem item)
{
return ToParameter(item, null);
Expand Down
21 changes: 21 additions & 0 deletions tests/neo.UnitTests/VM/UT_Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ public void TestEmit()
CollectionAssert.AreEqual(new[] { (byte)OpCode.PUSH0 }, sb.ToArray());
}

[TestMethod]
public void TestToJson()
{
var item = new VM.Types.Array();
item.Add(5);
item.Add("hello world");
item.Add(new byte[] { 1, 2, 3 });
item.Add(true);

Assert.AreEqual("{\"type\":\"Integer\",\"value\":\"5\"}", item[0].ToJson().ToString());
Assert.AreEqual("{\"type\":\"ByteString\",\"value\":\"aGVsbG8gd29ybGQ=\"}", item[1].ToJson().ToString());
Assert.AreEqual("{\"type\":\"ByteString\",\"value\":\"AQID\"}", item[2].ToJson().ToString());
Assert.AreEqual("{\"type\":\"Boolean\",\"value\":true}", item[3].ToJson().ToString());
Assert.AreEqual("{\"type\":\"Array\",\"value\":[{\"type\":\"Integer\",\"value\":\"5\"},{\"type\":\"ByteString\",\"value\":\"aGVsbG8gd29ybGQ=\"},{\"type\":\"ByteString\",\"value\":\"AQID\"},{\"type\":\"Boolean\",\"value\":true}]}", item.ToJson().ToString());

var item2 = new VM.Types.Map();
item2[1] = new Pointer(new Script(new byte[0]), 0);

Assert.AreEqual("{\"type\":\"Map\",\"value\":[{\"key\":{\"type\":\"Integer\",\"value\":\"1\"},\"value\":{\"type\":\"Pointer\",\"value\":0}}]}", item2.ToJson().ToString());
}

[TestMethod]
public void TestEmitAppCall1()
{
Expand Down

0 comments on commit 1170143

Please sign in to comment.