-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathJsonExamples.bf
156 lines (135 loc) · 4.26 KB
/
JsonExamples.bf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Reflection;
namespace Atma.Json.Tests
{
public static class Examples
{
[Serializable]
public struct Vec2<T>
{
public T x, y;
public this(T x, T y)
{
this.x = x;
this.y = y;
}
public override void ToString(String strBuffer)
{
strBuffer.Append(scope $"[x:{x:0.0}, y:{y:0.0}] ");
}
}
[Serializable]
public struct Vec3<T>
{
public Vec2<T> p;
public T z;
public this(Vec2<T> p, T z)
{
this.p = p;
this.z = z;
}
public override void ToString(String strBuffer)
{
strBuffer.Append(scope $"[x:{p.x:0.0}, y:{p.y:0.0}, z:{z:0.0}] ");
}
}
[Serializable]
public class StringRef
{
//you can create a new string or the runtime will create it for you if null
//the runtime will also delete and null this string if it finds {text:null}
public int x;
public String Text = new .() ~ delete _;
public this(int x)
{
this.x = x;
}
}
[Test]
public static void Examples()
{
//deserialize a simple struct from string
if (JsonConvert.Deserialize<Vec2<float>>("{x:1.1,y:7.9}") case .Ok(let v2))
Console.WriteLine(v2.ToString(..scope String()));//Output: [x:1.1, y:7.9]
//nested struct
if (JsonConvert.Deserialize<Vec3<float>>("{p:{x:1.5,y:9.1},z:4.4}") case .Ok(let v3))
Console.WriteLine(v3.ToString(..scope String()));//Output: [x:1.1, y:7.9]
//Class references
if (JsonConvert.Deserialize<StringRef>("{text:'hello world'}") case .Ok(let rf))
{
Console.WriteLine(rf.Text);//Output: [x:1.1, y:7.9]
delete rf;//be sure to delete your references
}
{
//You can also pass in your own references
let result = JsonConvert.Deserialize(..scope StringRef(10), "{text:'hello world'}");
Console.WriteLine(scope $"{result.Text}, {result.x}");
//delete result; //there is no need to delete since it was scoped
}
JsonConfig.AddConverter(new JsonVec2Converter());
//deseriealize simple struct from string
if (JsonConvert.Deserialize<Vec2<float>>("[1.1,7.9]") case .Ok(let v2))
Console.WriteLine(v2.ToString(..scope String()));//Output: [x:1.1, y:7.9]
{
//you can also pass in your own structs by pointer
let result = JsonConvert.Deserialize(..scope Vec2<float>[1]* , "[1.1,7.9]");
Console.WriteLine(result.ToString(..scope String()));//Output: [x:1.1, y:7.9]
}
}
//We can't pass in Vec2<> as the Converter type so we must manually do it as void
//we still want to use StructConverter because it handles, pointers, nullables, etc
public class JsonVec2Converter : JsonStructConverter<void>
{
public override bool CanConvert(Type type)
{
return GetGenericType(type) != null;
}
private Type GetGenericType(Type type)
{
if (let genericType = type as SpecializedGenericType && (genericType.UnspecializedType == typeof(Vec2<>)))
return genericType.GetGenericArg(0);
return null;
}
protected override void OnWriteJson(JsonWriter writer, Type type, void* target)
{
//since this is a struct, target points straight at the first element of vec2 (aka x)
let genericType = GetGenericType(type);
var ptr = (uint8*)target;
writer.WriteArrayStart();
{
//element count increases by 1 as well as marking the next WriteComma to actually write a comma
writer.WriteComma();
//write x
writer.WriteValue(genericType, ptr);
//move to next element base on the generic elements stride
ptr += genericType.Stride;
//write the first comma, element count == 2
writer.WriteComma();
//write y
writer.WriteValue(genericType, ptr);
}
writer.WriteArrayEnd();
}
protected override bool OnReadJson(JsonReader reader, Type type, void* target)
{
//since this is a struct, target points straight at the first element of vec2 (aka x)
let genericType = GetGenericType(type);
var ptr = (uint8*)target;
//we expect to find an array
if (!reader.Expect(.ArrayStart, let token))
return false;
//we expect to find to elements in the array
if (token.elements != 2)
return false;
//read x
if (!reader.Parse(genericType, ptr))
return false;
ptr += genericType.Stride;
//read y
if (!reader.Parse(genericType, ptr))
return false;
return reader.Expect(.ArrayEnd, ?);
}
}
}
}