Skip to content

Commit 509454a

Browse files
committed
unversal serialization
1 parent cc25eed commit 509454a

File tree

1 file changed

+286
-0
lines changed

1 file changed

+286
-0
lines changed

PLATFORM/C/LIB/serial.lsts

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
2+
type SerialVal = SerialUInt { val: U64 }
3+
| SerialInt { val: I64 }
4+
| SerialFlt { val: F64 }
5+
| SerialBool { val: U8 }
6+
| SerialStr { val: String }
7+
| SerialVec { val: Vector<SerialVal[]> }
8+
| SerialDict { val: HashtableEq<SerialVal[], SerialVal[]> }
9+
;
10+
11+
interface Serializable {
12+
let serialize(self: Serializable): SerialVal;
13+
}
14+
15+
interface Deserializable {
16+
let deserialize(val: SerialVal, ty: Type<Deserializable>): Deserializable;
17+
}
18+
19+
# TODO: failable casts between number types
20+
21+
type SerialVal => Serializable;
22+
type SerialVal => Deserializable;
23+
24+
let deserialize(val: SerialVal, ty: Type<SerialVal>): SerialVal = (
25+
val
26+
);
27+
28+
let serialize(val: SerialVal): SerialVal = (
29+
val
30+
);
31+
32+
type Bool => Serializable;
33+
type Bool => Deserializable;
34+
35+
let deserialize(vali: SerialVal, ty: Type<Bool>): Bool = (
36+
deserialize(vali,type(U64)) as Bool
37+
);
38+
39+
let serialize(val: Bool): SerialVal = (
40+
SerialBool { val }
41+
);
42+
43+
type U64 => Serializable;
44+
type U64 => Deserializable;
45+
46+
let deserialize(vali: SerialVal, ty: Type<U64>): U64 = (
47+
match vali {
48+
SerialBool { val=val } => ( val as U64 );
49+
SerialUInt { val=val } => ( val );
50+
SerialInt { val=val } => (
51+
if val < 0 {
52+
fail("cannot deserialize negative int to u64");
53+
};
54+
val as U64
55+
);
56+
SerialFlt { val=val } => (
57+
if val != ((val as U64) as F64) {
58+
fail("cannot deserialize decimal number to u64");
59+
};
60+
if val < 0 {
61+
fail("cannot deserialize negative number to u64");
62+
};
63+
val as U64
64+
);
65+
SerialStr { val=val } => ( to-u64(val) );
66+
other => ( fail("cannot deserialize u64 from this SerialVal"); );
67+
}
68+
);
69+
70+
let serialize(val: U64): SerialVal = (
71+
SerialUInt { val }
72+
);
73+
74+
type I64 => Serializable;
75+
type I64 => Deserializable;
76+
77+
let deserialize(vali: SerialVal, ty: Type<I64>): I64 = (
78+
match vali {
79+
SerialBool { val=val } => ( val as I64 );
80+
SerialUInt { val=val } => ( val as I64 );
81+
SerialInt { val=val } => ( val );
82+
SerialFlt { val=val } => (
83+
if val != ((val as I64) as F64) {
84+
fail("cannot deserialize decimal number to i64");
85+
};
86+
val as I64
87+
);
88+
SerialStr { val=val } => ( to-i64(val) );
89+
other => ( fail("cannot deserialize i64 from this SerialVal"); );
90+
}
91+
);
92+
93+
let serialize(val: I64): SerialVal = (
94+
SerialInt { val }
95+
);
96+
97+
type F64 => Serializable;
98+
type F64 => Deserializable;
99+
100+
let deserialize(vali: SerialVal, ty: Type<F64>): F64 = (
101+
match vali {
102+
SerialBool { val=val } => ( val as F64 );
103+
SerialUInt { val=val } => ( val as F64 );
104+
SerialInt { val=val } => ( val as F64 );
105+
SerialFlt { val=val } => ( val );
106+
SerialStr { val=val } => ( to-f64(val) );
107+
other => ( fail("cannot deserialize f64 from this SerialVal"); );
108+
}
109+
);
110+
111+
let serialize(val: F64): SerialVal = (
112+
SerialFlt { val }
113+
);
114+
115+
type String => Serializable;
116+
type String => Deserializable;
117+
118+
let deserialize(vali: SerialVal, ty: Type<String>): String = (
119+
match vali {
120+
SerialStr { val=val } => ( val );
121+
other => ( fail("cannot deserialize string from this SerialVal"); );
122+
}
123+
);
124+
125+
let serialize(val: String): SerialVal = (
126+
SerialStr { val }
127+
);
128+
129+
type CString => Serializable;
130+
type CString => Deserializable;
131+
132+
let deserialize(vali: SerialVal, ty: Type<CString>): CString = (
133+
match vali {
134+
SerialStr { val=val } => ( untern(val) );
135+
other => ( fail("cannot deserialize string from this SerialVal"); );
136+
}
137+
);
138+
139+
let serialize(val: CString): SerialVal = (
140+
SerialStr { (to-smart-string(val)) }
141+
);
142+
143+
type Iterable<Serializable> => Serializable;
144+
type FromVector<Deserializable> => Deserializable;
145+
146+
let deserialize(vali: SerialVal, ty: Type<ot+FromVector<eltt+Deserializable>>): ot = (
147+
match vali {
148+
SerialVec { val=val } => (
149+
let out = mk-vector(type(eltt), val.length());
150+
for x in val.unsafe-iter() {
151+
out = out.push(deserialize(x,type(eltt)));
152+
};
153+
out.move-to(ty)
154+
);
155+
r => ( fail("can only deserialize collection from serialvec"); );
156+
}
157+
);
158+
159+
let serialize(self: Iterable<t+Serializable>): SerialVal = (
160+
let out = mk-vector(type(SerialVal), length-or-zero(self));
161+
for x in self.unsafe-iter() {
162+
out = out.push(close(serialize(x)));
163+
};
164+
SerialVec { out }
165+
);
166+
167+
type HashtableEq<Serializable,Serializable> => Serializable;
168+
type HashtableEq<Deserializable,Deserializable> => Deserializable;
169+
170+
let deserialize(val: SerialVal, ty: Type<HashtableEq<k+Deserializable,v+Deserializable>>): HashtableEq<k,v> = (
171+
let out = {} :: HashtableEq<k,v>;
172+
match val {
173+
SerialDict { val=val } => (
174+
for kv in val.unsafe-iter() {
175+
let k = deserialize(open(kv.first), type(k));
176+
let v = deserialize(open(kv.second), type(v));
177+
out = out.bind(k, v);
178+
};
179+
);
180+
r => ( fail("can only deserialize map from serialdict") );
181+
};
182+
out
183+
);
184+
185+
let serialize(self: HashtableEq<k+Serializable,v+Serializable>): SerialVal = (
186+
let out = {} :: HashtableEq<SerialVal, SerialVal>;
187+
188+
for x in self.unsafe-iter() {
189+
out = out.bind(
190+
close(serialize(x.first)),
191+
close(serialize(x.second)));
192+
};
193+
194+
SerialDict { out }
195+
);
196+
197+
type JsonSerializeCfg = JsonSerializeCfg { pretty: U8, indent: U64 };
198+
199+
let to-smart-string(self: SerialVal): String = (
200+
self.to-json(JsonSerializeCfg { true, 2 }, 0)
201+
);
202+
203+
let to-smart-string(self: Serializable): String = (
204+
to-smart-string(serialize(self))
205+
);
206+
207+
let .to-json(self: SerialVal, cfg: JsonSerializeCfg, depth: U64): String = (
208+
match self {
209+
SerialUInt { val=val } => ( to-smart-string(val) );
210+
SerialInt { val=val } => ( to-smart-string(val) );
211+
SerialFlt { val=val } => ( to-smart-string(val) );
212+
213+
SerialBool { val=val } => (
214+
if val { "true" }
215+
else { "false" }
216+
);
217+
218+
SerialStr { val=val } => ( "\"\{val}\"" );
219+
220+
SerialVec { val=val } => (
221+
let out = "[";
222+
if cfg.pretty {
223+
let first = true;
224+
for x in val.unsafe-iter() {
225+
if first {
226+
first = false;
227+
} else {
228+
out = out + ",\n";
229+
};
230+
out = out + " ".repeat(depth * cfg.indent);
231+
out = out + open(x).to-json(cfg, depth + 1);
232+
};
233+
if val.length() > 0 {
234+
out = out + "\n";
235+
};
236+
} else {
237+
let first = true;
238+
for x in val.unsafe-iter() {
239+
if first {
240+
first = false;
241+
} else {
242+
out = out + ", ";
243+
};
244+
out = out + open(x).to-json(cfg, depth + 1);
245+
};
246+
};
247+
out = out + "]";
248+
);
249+
250+
SerialDict { val=val } => (
251+
let out = "{";
252+
if cfg.pretty {
253+
let first = true;
254+
let any = false;
255+
for x in val.unsafe-iter() {
256+
any = true;
257+
if first {
258+
first = false;
259+
} else {
260+
out = out + ",\n";
261+
};
262+
out = out + " ".repeat(depth * cfg.indent);
263+
out = out + open(x.first).to-json(cfg, depth + 1);
264+
out = out + ": ";
265+
out = out + open(x.second).to-json(cfg, depth + 1);
266+
};
267+
if any {
268+
out = out + "\n";
269+
};
270+
} else {
271+
let first = true;
272+
for x in val.unsafe-iter() {
273+
if first {
274+
first = false;
275+
} else {
276+
out = out + ", ";
277+
};
278+
out = out + open(x.first).to-json(cfg, depth + 1);
279+
out = out + ": ";
280+
out = out + open(x.second).to-json(cfg, depth + 1);
281+
};
282+
};
283+
out = out + "}";
284+
);
285+
}
286+
);

0 commit comments

Comments
 (0)