Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ToJson overload #2671

Merged
merged 7 commits into from
Mar 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 83 additions & 26 deletions src/neo/VM/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,48 +278,105 @@ public static byte[] MakeScript(this UInt160 scriptHash, string method, params o
/// Converts the <see cref="StackItem"/> to a JSON object.
/// </summary>
/// <param name="item">The <see cref="StackItem"/> to convert.</param>
/// <param name="maxSize">The maximum size in bytes of the result.</param>
/// <returns>The <see cref="StackItem"/> represented by a JSON object.</returns>
public static JObject ToJson(this StackItem item)
public static JObject ToJson(this StackItem item, int maxSize = int.MaxValue)
{
return ToJson(item, null);
return ToJson(item, null, ref maxSize);
}

private static JObject ToJson(StackItem item, HashSet<StackItem> context)
/// <summary>
/// Converts the <see cref="EvaluationStack"/> to a JSON object.
/// </summary>
/// <param name="stack">The <see cref="EvaluationStack"/> to convert.</param>
/// <param name="maxSize">The maximum size in bytes of the result.</param>
/// <returns>The <see cref="EvaluationStack"/> represented by a JSON object.</returns>
public static JArray ToJson(this EvaluationStack stack, int maxSize = int.MaxValue)
{
if (maxSize <= 0) throw new ArgumentOutOfRangeException(nameof(maxSize));
maxSize -= 2/*[]*/+ Math.Max(0, (stack.Count - 1))/*,*/;
JArray result = new();
foreach (var item in stack)
result.Add(ToJson(item, null, ref maxSize));
if (maxSize < 0) throw new InvalidOperationException("Max size reached.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (maxSize < 0) throw new InvalidOperationException("Max size reached.");

return result;
}

private static JObject ToJson(StackItem item, HashSet<StackItem> context, ref int maxSize)
{
JObject json = new();
json["type"] = item.Type;
JObject json = new()
{
["type"] = item.Type
};
JObject value = null;
maxSize -= 11/*{"type":""}*/+ item.Type.ToString().Length;
switch (item)
{
case Array array:
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(array)) throw new InvalidOperationException();
json["value"] = new JArray(array.Select(p => ToJson(p, context)));
break;
{
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(array)) throw new InvalidOperationException();
maxSize -= 2/*[]*/+ Math.Max(0, (array.Count - 1))/*,*/;
JArray a = new();
foreach (StackItem stackItem in array)
a.Add(ToJson(stackItem, context, ref maxSize));
value = a;
break;
}
case Boolean boolean:
json["value"] = boolean.GetBoolean();
break;
{
bool b = boolean.GetBoolean();
maxSize -= b ? 4/*true*/: 5/*false*/;
value = b;
break;
}
case Buffer _:
case ByteString _:
json["value"] = Convert.ToBase64String(item.GetSpan());
break;
{
string s = Convert.ToBase64String(item.GetSpan());
maxSize -= 2/*""*/+ s.Length;
value = s;
break;
}
case Integer integer:
json["value"] = integer.GetInteger().ToString();
break;
{
string s = integer.GetInteger().ToString();
maxSize -= 2/*""*/+ s.Length;
value = s;
break;
}
case Map map:
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(map)) throw new InvalidOperationException();
json["value"] = new JArray(map.Select(p =>
{
JObject item = new();
item["key"] = ToJson(p.Key, context);
item["value"] = ToJson(p.Value, context);
return item;
}));
break;
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(map)) throw new InvalidOperationException();
maxSize -= 2/*[]*/+ Math.Max(0, (map.Count - 1))/*,*/;
JArray a = new();
foreach (var (k, v) in map)
{
maxSize -= 17/*{"key":,"value":}*/;
JObject i = new()
{
["key"] = ToJson(k, context, ref maxSize),
["value"] = ToJson(v, context, ref maxSize)
};
a.Add(i);
}
value = a;
break;
}
case Pointer pointer:
json["value"] = pointer.Position;
break;
{
maxSize -= pointer.Position.ToString().Length;
value = pointer.Position;
break;
}
}
if (value is not null)
{
maxSize -= 9/*,"value":*/;
json["value"] = value;
}
if (maxSize < 0) throw new InvalidOperationException("Max size reached.");
return json;
}

Expand Down