Skip to content

Commit 2689105

Browse files
committed
VM: Support for conversion between strings and char arrays
1 parent 0bf88fa commit 2689105

File tree

2 files changed

+93
-4
lines changed

2 files changed

+93
-4
lines changed

Phantasma.Tests/VMTests.cs

+19
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,25 @@ public void ArrayObjects()
286286
}
287287
}
288288

289+
[TestMethod]
290+
public void StringUnicodeArrays()
291+
{
292+
var original = "Hello Phantasma";
293+
294+
var obj = VMObject.FromObject(original);
295+
Assert.IsTrue(obj.Type == VMType.String);
296+
297+
var temp = VMObject.CastTo(obj, VMType.Struct);
298+
Assert.IsTrue(temp.Type == VMType.Struct);
299+
300+
var elements = temp.GetChildren();
301+
Assert.IsTrue(elements.Count == original.Length);
302+
303+
var result = temp.AsString();
304+
305+
Assert.IsTrue(original == result);
306+
}
307+
289308
public struct TestStruct : ISerializable
290309
{
291310
public string Name;

Phantasma.VM/VMObject.cs

+74-4
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,37 @@ public string AsString()
190190
return "Interop:" + Data.GetType().Name;
191191
}
192192
case VMType.Struct:
193-
using (var stream = new MemoryStream())
193+
VMType arrayType = GetArrayType();
194+
if (arrayType == VMType.Number) // convert array of unicode numbers into a string
195+
{
196+
var children = GetChildren();
197+
var sb = new StringBuilder();
198+
199+
for (int i = 0; i < children.Count; i++)
200+
{
201+
var key = VMObject.FromObject(i);
202+
var val = children[key];
203+
204+
var ch = (char)((uint)val.AsNumber());
205+
206+
sb.Append(ch);
207+
}
208+
209+
return sb.ToString();
210+
}
211+
else
194212
{
195-
using (var writer = new BinaryWriter(stream))
213+
using (var stream = new MemoryStream())
196214
{
197-
SerializeData(writer);
215+
using (var writer = new BinaryWriter(stream))
216+
{
217+
SerializeData(writer);
218+
}
219+
return Convert.ToBase64String(stream.ToArray());
198220
}
199-
return Convert.ToBase64String(stream.ToArray());
200221
}
201222

223+
202224
case VMType.Bool:
203225
return ((bool)Data) ? "true" : "false";
204226

@@ -211,6 +233,46 @@ public string AsString()
211233
}
212234
}
213235

236+
// this method checks if the VMObject is an array by checking the following rules
237+
// a) must be a struct
238+
// b) all keys of the struct must be numeric indexes from 0 to count-1
239+
// c) all element values must have same type
240+
public VMType GetArrayType()
241+
{
242+
if (this.Type != VMType.Struct)
243+
{
244+
return VMType.None;
245+
}
246+
247+
var children = GetChildren();
248+
249+
VMType result = VMType.None;
250+
251+
for (int i=0; i<children.Count; i++)
252+
{
253+
var key = VMObject.FromObject(i);
254+
255+
if (!children.ContainsKey(key))
256+
{
257+
return VMType.None;
258+
}
259+
260+
var val = children[key];
261+
262+
if (result == VMType.None)
263+
{
264+
result = val.Type;
265+
}
266+
else
267+
if (val.Type != result)
268+
{
269+
return VMType.None;
270+
}
271+
}
272+
273+
return result;
274+
}
275+
214276
public byte[] AsByteArray()
215277
{
216278
switch (this.Type)
@@ -937,6 +999,14 @@ public static VMObject CastTo(VMObject srcObj, VMType type)
937999
case VMType.Struct:
9381000
switch (srcObj.Type)
9391001
{
1002+
// this allow casting a string into char array (represented as unicode numbers)
1003+
case VMType.String:
1004+
{
1005+
var str = srcObj.AsString();
1006+
var chars = str.ToCharArray().Select(x => new BigInteger((uint)x)).ToArray();
1007+
return VMObject.FromArray(chars);
1008+
}
1009+
9401010
case VMType.Object: return CastViaReflection(srcObj.Data, 0);
9411011

9421012
default: throw new Exception($"invalid cast: {srcObj.Type} to {type}");

0 commit comments

Comments
 (0)