@@ -129,3 +129,61 @@ external stringify: t -> string = "stringify"
129129 [@@ bs.val] [@@ bs.scope "JSON" ]
130130external stringifyWithSpace : t -> (_ [@ bs.as {json| null| json}]) -> int -> string = " stringify"
131131 [@@ bs.val] [@@ bs.scope "JSON" ]
132+
133+
134+ (* in memory modification does not work until your root is
135+ actually None, so we need wrap it as `[v]` and
136+ return the first element instead *)
137+
138+ let patch : _ -> _ = [% raw{| function (json) {
139+ var x = [json];
140+ var q = [{ kind : 0 , i : 0 , parent : x }];
141+ while (q.length != = 0 ) {
142+ // begin pop the stack
143+ var cur = q[q.length - 1 ];
144+ if (cur.kind === 0 ) {
145+ cur.val = cur.parent[cur.i]; // patch the undefined value for array
146+ if (++ cur.i === cur.parent.length) {
147+ q.pop() ;
148+ }
149+ } else {
150+ q.pop() ;
151+ }
152+ // finish
153+ var task = cur.val;
154+ if (typeof task === " object" ) {
155+ if (Array. isArray(task) && task.length != = 0 ) {
156+ q.push({ kind : 0 , i : 0 , parent : task , val : undefined });
157+ } else {
158+ for (var k in task) {
159+ if (k === " RE_PRIVATE_NONE" ) {
160+ if (cur.kind === 0 ) {
161+ cur.parent[cur.i - 1 ] = undefined;
162+ } else {
163+ cur.parent[cur.i] = undefined;
164+ }
165+ continue;
166+ }
167+ q.push({ kind : 1 , i : k , parent : task , val : task [k] });
168+ }
169+ }
170+ }
171+ }
172+ return x[0 ];
173+ }
174+ | }]
175+
176+
177+ let serialize (type t ) (x : t ) : string option = [% raw{| function(obj){
178+ return JSON. stringify(obj,function(_,value){
179+ if (value=== undefined){
180+ return {RE_PRIVATE_NONE : true }
181+ }
182+ return value
183+ })
184+ }
185+ | }] x
186+
187+ let deserializeExn (s : string ) : 'a =
188+ patch (parseExn s)
189+
0 commit comments