Skip to content

Commit b0e6265

Browse files
authored
chore: Improve data serializer (#150)
1 parent 1c488ce commit b0e6265

File tree

3 files changed

+93
-28
lines changed

3 files changed

+93
-28
lines changed

addons/vest/plugin.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
name="vest"
44
description="A unit testing library for Godot"
55
author="Tamás Gálffy"
6-
version="1.3.2"
6+
version="1.3.3"
77
script="plugin.gd"

addons/vest/vest-data-serializer.gd

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ static func serialize(data: Variant, max_depth: int = MAX_DEPTH) -> Variant:
1414
push_error("Data structure too deep to serialize! Is there a circular reference?")
1515
return str(data)
1616

17+
var depth := max_depth - 1
18+
19+
if data == null:
20+
return null
21+
1722
match typeof(data):
1823
# Numbers
1924
TYPE_BOOL, TYPE_INT, TYPE_FLOAT:
@@ -24,35 +29,76 @@ static func serialize(data: Variant, max_depth: int = MAX_DEPTH) -> Variant:
2429
return str(data)
2530

2631
# Linalg
27-
TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I, \
28-
TYPE_VECTOR3, TYPE_VECTOR3I, TYPE_VECTOR4, TYPE_VECTOR4I, \
29-
TYPE_PLANE, TYPE_QUATERNION:
30-
return str(data)
32+
TYPE_VECTOR2, TYPE_VECTOR2I:
33+
return [data.x, data.y]
34+
35+
TYPE_VECTOR3, TYPE_VECTOR3I:
36+
return [data.x, data.y, data.z]
37+
38+
TYPE_VECTOR4, TYPE_VECTOR4I, TYPE_QUATERNION:
39+
return [data.x, data.y, data.z, data.w]
40+
41+
TYPE_RECT2, TYPE_RECT2I, TYPE_AABB:
42+
return [serialize(data.position, depth), serialize(data.size, depth)]
43+
44+
TYPE_PLANE:
45+
var plane := data as Plane
46+
return [plane.x, plane.y, plane.z, plane.d, serialize(plane.normal, depth)]
47+
48+
TYPE_TRANSFORM2D:
49+
var xform := data as Transform2D
50+
return [
51+
serialize(xform.x, depth),
52+
serialize(xform.y, depth),
53+
serialize(xform.origin, depth)
54+
]
55+
56+
TYPE_TRANSFORM3D:
57+
var xform := data as Transform3D
58+
return [serialize(xform.basis, depth)] + [serialize(xform.origin, depth)]
59+
60+
TYPE_BASIS:
61+
var basis := data as Basis
62+
return [
63+
serialize(basis.x, depth),
64+
serialize(basis.y, depth),
65+
serialize(basis.z, depth)
66+
]
3167

32-
TYPE_TRANSFORM2D, TYPE_TRANSFORM3D, TYPE_AABB, TYPE_BASIS, \
3368
TYPE_PROJECTION:
34-
return str(data)
69+
var projection := data as Projection
70+
return [
71+
serialize(projection.x, depth),
72+
serialize(projection.y, depth),
73+
serialize(projection.z, depth),
74+
serialize(projection.w, depth)
75+
]
3576

3677
# Other
37-
TYPE_COLOR, TYPE_RID, TYPE_CALLABLE, TYPE_SIGNAL:
78+
TYPE_COLOR:
79+
var color := data as Color
80+
return [color.r, color.g, color.b, color.a]
81+
82+
TYPE_RID, TYPE_CALLABLE, TYPE_SIGNAL:
3883
return str(data)
3984

4085
# Complex
4186
TYPE_OBJECT:
4287
var object := data as Object
4388
if object.has_method("_to_vest"):
44-
return serialize(object._to_vest(), max_depth - 1)
45-
return str(object) # TODO: Convert to dictionary instead
89+
return serialize(object._to_vest(), depth)
90+
91+
return serialize(_object_to_map(object), depth)
4692

4793
# Arrays
4894
TYPE_PACKED_BYTE_ARRAY, TYPE_PACKED_INT32_ARRAY, TYPE_PACKED_INT64_ARRAY, \
4995
TYPE_PACKED_FLOAT32_ARRAY, TYPE_PACKED_FLOAT64_ARRAY, TYPE_PACKED_STRING_ARRAY, \
5096
TYPE_PACKED_VECTOR2_ARRAY, TYPE_PACKED_VECTOR3_ARRAY, TYPE_PACKED_COLOR_ARRAY:
51-
return serialize(Array(data), max_depth - 1)
97+
return serialize(Array(data), depth)
5298

5399
TYPE_ARRAY:
54100
var array := data as Array
55-
return array.map(func(it): return serialize(it, max_depth - 1))
101+
return array.map(func(it): return serialize(it, depth))
56102

57103
# Dictionary
58104
TYPE_DICTIONARY:
@@ -61,8 +107,22 @@ static func serialize(data: Variant, max_depth: int = MAX_DEPTH) -> Variant:
61107

62108
for key in dict:
63109
var value = dict.get(key)
64-
result[serialize(key, max_depth - 1)] = serialize(value, max_depth - 1)
110+
result[serialize(key, max_depth - 1)] = serialize(value, depth)
65111
return result
66112

67113
# Default
68114
_: return str(data)
115+
116+
static func _object_to_map(object: Object) -> Dictionary:
117+
var properties := object.get_property_list().map(func(prop): return prop["name"])
118+
var script := object.get_script() as Script
119+
120+
if script != null:
121+
properties = script.get_script_property_list().map(func(prop): return prop["name"])
122+
123+
var result := {}
124+
for property in properties:
125+
if property.contains(" "): continue # Skip invalid props
126+
result[property] = object.get(property)
127+
128+
return result

tests/vest-data-serializer.test.gd

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,21 @@ func suite():
1414
["float", 78.2, 78.2],
1515
["string", "foo", "foo"],
1616
["array", ["foo", [1, 2]], ["foo", [1, 2]]],
17+
["vector", Vector3.ONE, [1., 1., 1.]],
18+
["color", Color.RED, [1., 0., 0., 1.]],
19+
["basis", Basis.FLIP_X, [[-1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]],
1720
["PackedByteArray", PackedByteArray([1, 75, 3]), [1, 75, 3]],
18-
["object", SerializableObject.of(2), { "value": 2 }],
19-
["dictionary", { Vector3i.ONE: SerializableObject.of(2) }, { "(1, 1, 1)": { "value": 2 } }],
21+
["serializable object", SerializableObject.of(2), { "value": 2 }],
22+
["object", UnknownObject.of(2), { "_value": 2 }],
23+
["dictionary", { Vector3i.ONE: SerializableObject.of(2) }, { [1, 1, 1]: { "value": 2 } }],
2024
["nested",
2125
{ "foo": SerializableObject.of([1, SerializableObject.of(2)]) },
2226
{ "foo": { "value": [1, { "value": 2 }] } }
2327
],
24-
["circular reference", ref_a, { "value": { "value": { "value": { "value": "SerializableObject" }}}}]
28+
["circular reference", ref_a, { "value": { "value": { "value": { "value": "SerializableObject" }}}}],
29+
["null", null, null]
2530
]
2631

27-
# Godot 4.4 stringifies slightly differently, these cases depend on version
28-
if Engine.get_version_info().hex >= 0x040400:
29-
cases += [
30-
["vector", Vector3.ONE, "(1.0, 1.0, 1.0)"],
31-
["color", Color.RED, "(1.0, 0.0, 0.0, 1.0)"]
32-
]
33-
else:
34-
cases += [
35-
["vector", Vector3.ONE, "(1, 1, 1)"],
36-
["color", Color.RED, "(1, 0, 0, 1)"],
37-
]
38-
3932
for case in cases:
4033
var name := case[0] as String
4134
var to_serialize = case[1]
@@ -59,3 +52,15 @@ class SerializableObject:
5952

6053
func _to_string() -> String:
6154
return "SerializableObject"
55+
56+
class UnknownObject:
57+
var _value: Variant
58+
59+
static func of(p_value: Variant) -> UnknownObject:
60+
return UnknownObject.new(p_value)
61+
62+
func _init(p_value: Variant):
63+
_value = p_value
64+
65+
func _to_string() -> String:
66+
return "UnknownObject"

0 commit comments

Comments
 (0)