Skip to content

Commit

Permalink
Improve option serializing
Browse files Browse the repository at this point in the history
  • Loading branch information
DZakh committed Sep 8, 2024
1 parent b198996 commit 09d926a
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 116 deletions.
2 changes: 1 addition & 1 deletion packages/tests/src/core/Example_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ test("Compiled serialize code snapshot", t => {
t->U.assertCompiledCode(
~schema=filmSchema,
~op=#Serialize,
`i=>{let v0=i["tags"],v4,v5=i["rating"],v6,v7=i["deprecatedAgeRestriction"],v8;if(v0!==void 0){let v1=e[0](v0);v4=v1}try{if(v5!=="G"){e[1](v5)}v6=v5}catch(e0){try{if(v5!=="PG"){e[2](v5)}v6=v5}catch(e1){try{if(v5!=="PG13"){e[3](v5)}v6=v5}catch(e2){try{if(v5!=="R"){e[4](v5)}v6=v5}catch(e3){e[5]([e0,e1,e2,e3,])}}}}if(v7!==void 0){v8=e[6](v7)}return {"Id":i["id"],"Title":i["title"],"Tags":v4,"Rating":v6,"Age":v8,}}`,
`i=>{let v0=i["tags"],v3=i["rating"],v4,v5=i["deprecatedAgeRestriction"],v6;try{if(v3!=="G"){e[0](v3)}v4=v3}catch(e0){try{if(v3!=="PG"){e[1](v3)}v4=v3}catch(e1){try{if(v3!=="PG13"){e[2](v3)}v4=v3}catch(e2){try{if(v3!=="R"){e[3](v3)}v4=v3}catch(e3){e[4]([e0,e1,e2,e3,])}}}}if(v5!==void 0){v6=e[5](v5)}return {"Id":i["id"],"Title":i["title"],"Tags":v0,"Rating":v4,"Age":v6,}}`,
)
})
7 changes: 1 addition & 6 deletions packages/tests/src/core/S_Option_getOrWith_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,5 @@ test("Compiled async parse code snapshot", t => {
test("Compiled serialize code snapshot", t => {
let schema = S.bool->S.option->S.Option.getOrWith(() => false)

t->U.assertCompiledCode(
~schema,
~op=#Serialize,
// TODO: It can be simplified to noop
`i=>{let v0;if(i!==void 0){v0=e[0](i)}return v0}`,
)
t->U.assertCompiledCodeIsNoop(~schema, ~op=#Serialize)
})
6 changes: 1 addition & 5 deletions packages/tests/src/core/S_Option_getOr_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,5 @@ test("Compiled async parse code snapshot", t => {
test("Compiled serialize code snapshot", t => {
let schema = S.bool->S.option->S.Option.getOr(false)

t->U.assertCompiledCode(
~schema,
~op=#Serialize,
`i=>{let v0;if(i!==void 0){v0=e[0](i)}return v0}`,
)
t->U.assertCompiledCodeIsNoop(~schema, ~op=#Serialize)
})
8 changes: 8 additions & 0 deletions packages/tests/src/core/S_name_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,12 @@ test("Name of renamed schema", t => {
`Failed parsing at root. Reason: Expected Ethers.BigInt, received "smth"`,
(),
)
t->U.assertErrorResult(
%raw(`"smth"`)->S.serializeToUnknownWith(S.null(S.never)->S.setName("Ethers.BigInt")),
{
path: S.Path.empty,
operation: SerializeToUnknown,
code: InvalidType({expected: S.never->S.toUnknown, received: "smth"->Obj.magic}),
},
)
})
6 changes: 3 additions & 3 deletions packages/tests/src/core/S_null_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ module Common = {
t->Assert.is(schema->S.reverse->S.reverse, schema->S.toUnknown, ())
})

let serializeCode = `let v0;if(i!==void 0){v0=e[0](i)}else{v0=null}return v0`
let serializeCode = `let v0;if(i!==void 0){v0=i}else{v0=null}return v0`
test("Compiled serialize code snapshot", t => {
let schema = factory()
t->U.assertCompiledCode(~schema, ~op=#Serialize, `i=>{${serializeCode}}`)
Expand All @@ -73,7 +73,7 @@ module Common = {
t->U.assertCompiledCode(
~schema=schema->S.reverse,
~op=#Parse,
`i=>{if(i!==void 0&&(typeof i!=="string")){e[1](i)}${serializeCode}}`,
`i=>{if(i!==void 0&&(typeof i!=="string")){e[0](i)}${serializeCode}}`,
)
})

Expand Down Expand Up @@ -156,6 +156,6 @@ test("Serializes Some(None) to null for null nested in option", t => {
t->U.assertCompiledCode(
~schema,
~op=#Serialize,
`i=>{let v2;if(i!==void 0){let v0=e[0](i),v1;if(v0!==void 0){v1=e[1](v0)}else{v1=null}v2=v1}return v2}`,
`i=>{let v2;if(i!==void 0){let v0=e[0](i),v1;if(v0!==void 0){v1=v0}else{v1=null}v2=v1}return v2}`,
)
})
2 changes: 1 addition & 1 deletion packages/tests/src/core/S_nullable_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ module NullCommon = {
t->U.assertCompiledCode(
~schema,
~op=#Serialize,
`i=>{let v2;if(i!==void 0){let v0=e[0](i),v1;if(v0!==void 0){v1=e[1](v0)}else{v1=null}v2=v1}return v2}`,
`i=>{let v2;if(i!==void 0){let v0=e[0](i),v1;if(v0!==void 0){v1=v0}else{v1=null}v2=v1}return v2}`,
)
})

Expand Down
5 changes: 2 additions & 3 deletions packages/tests/src/core/S_option_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,9 @@ module Common = {
)
})

test("Reverse to S.option", t => {
test("Reverse to self", t => {
let schema = factory()
t->Assert.not(schema->S.reverse, schema->S.toUnknown, ()) // not self
t->U.assertEqualSchemas(schema->S.reverse, schema->S.toUnknown)
t->Assert.is(schema->S.reverse, schema->S.toUnknown, ())
})

test("Succesfully uses reversed schema for parsing back to initial value", t => {
Expand Down
92 changes: 47 additions & 45 deletions src/S_Core.bs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -654,11 +654,7 @@ function isAsyncParse(schema) {
}

function reverse(schema) {
var reversed = schema.r();
reversed.r = (function () {
return schema;
});
return reversed;
return schema.r();
}

function parseAnyOrRaiseWith(any, schema) {
Expand Down Expand Up @@ -861,7 +857,7 @@ function initialAssertOrRaise(unknown) {

function initialSerializeToUnknownOrRaise(unknown) {
var schema = this;
var reversed = reverse(schema);
var reversed = schema.r();
var operation = build(reversed.b, reversed, "SerializeToUnknown", serializeFinalizer);
schema.serializeOrThrow = operation;
return operation(unknown);
Expand All @@ -875,7 +871,7 @@ function initialSerializeOrRaise(unknown) {
_0: schema
}, "SerializeToJson", "");
}
var reversed = reverse(schema);
var reversed = schema.r();
var operation = build(reversed.b, reversed, "SerializeToJson", serializeFinalizer);
schema.serializeToJsonOrThrow = operation;
return operation(unknown);
Expand Down Expand Up @@ -922,7 +918,14 @@ function makeSchema(name, tagged, metadataMap, builder, maybeTypeFilter, reverse
return {
t: tagged,
n: name,
r: reverse,
r: (function () {
var original = this;
var reversed = reverse.call(original);
reversed.r = (function () {
return original;
});
return reversed;
}),
b: builder,
f: maybeTypeFilter,
i: 0,
Expand Down Expand Up @@ -1068,7 +1071,9 @@ function recursive(fn) {
function setName(schema, name) {
return makeSchema((function () {
return name;
}), schema.t, schema.m, schema.b, schema.f, schema.r);
}), schema.t, schema.m, schema.b, schema.f, (function () {
return schema.r();
}));
}

function internalRefine(schema, refiner) {
Expand Down Expand Up @@ -1210,21 +1215,30 @@ function $$default(schema) {
}

function builder(b, input, selfSchema, path) {
var isNull = (selfSchema.t.TAG === "Null");
var isNullInput = selfSchema.t.TAG === "Null";
var reversed = selfSchema.r();
var isNullOutput = reversed.t.TAG === "Null";
var childSchema = selfSchema.t._0;
var bb = scope(b);
var itemOutput = childSchema.b(bb, input, childSchema, path);
var itemInput;
if (!isNullOutput && (b.g.o === "SerializeToJson" || b.g.o === "SerializeToUnknown")) {
var value = Caml_option.valFromOption;
itemInput = val(bb, "e[" + (bb.g.e.push(value) - 1) + "](" + $$var(b, input) + ")");
} else {
itemInput = input;
}
var itemOutput = childSchema.b(bb, itemInput, childSchema, path);
var itemCode = allocateScope(bb);
var isTransformed = isNull || itemOutput !== input;
var inputLiteral = isNullInput ? "null" : "void 0";
var ouputLiteral = isNullOutput ? "null" : "void 0";
var isTransformed = inputLiteral !== ouputLiteral || itemOutput !== input;
var output = isTransformed ? ({
s: b,
a: itemOutput.a
}) : input;
if (itemCode !== "" || isTransformed) {
b.c = b.c + ("if(" + $$var(b, input) + "!==" + (
isNull ? "null" : "void 0"
) + "){" + itemCode + set(b, output, itemOutput) + "}" + (
isNull || output.a ? "else{" + set(b, output, val(b, "void 0")) + "}" : ""
b.c = b.c + ("if(" + $$var(b, input) + "!==" + inputLiteral + "){" + itemCode + set(b, output, itemOutput) + "}" + (
inputLiteral !== ouputLiteral || output.a ? "else{" + set(b, output, val(b, ouputLiteral)) + "}" : ""
));
}
return output;
Expand All @@ -1240,34 +1254,11 @@ function maybeTypeFilter(schema, inlinedNoneValue) {

}

function reverse$1() {
var original = this;
var isNull = (original.t.TAG === "Null");
var originalChild = original.t._0;
var child = originalChild.r();
return makeReverseSchema(containerName, {
TAG: "Option",
_0: child
}, empty, (function (b, input, param, path) {
var output = allocateVal(b);
var inputVar = $$var(b, input);
var bb = scope(b);
var value = Caml_option.valFromOption;
var input$1 = map(bb, "e[" + (bb.g.e.push(value) - 1) + "]", input);
var itemOutput = child.b(bb, input$1, child, path);
var itemCode = allocateScope(bb);
b.c = b.c + ("if(" + inputVar + "!==void 0){" + itemCode + set(b, output, itemOutput) + "}" + (
isNull ? "else{" + setInlined(b, output, "null") + "}" : ""
));
return output;
}), maybeTypeFilter(child, "void 0"));
}

function factory(schema) {
return makeSchema(containerName, {
TAG: "Option",
_0: schema
}, empty, builder, maybeTypeFilter(schema, "void 0"), reverse$1);
}, empty, builder, maybeTypeFilter(schema, "void 0"), onlyChild(factory, schema));
}

function getWithDefault(schema, $$default) {
Expand All @@ -1279,7 +1270,16 @@ function getWithDefault(schema, $$default) {
return val(b, inputVar + "===void 0?" + tmp + ":" + inputVar);
}));
}), schema.f, (function () {
return schema.r();
var reversed = schema.r();
var child = reversed.t;
if (typeof child !== "object") {
return reversed;
}
if (child.TAG !== "Option") {
return reversed;
}
var child$1 = child._0;
return makeReverseSchema(child$1.n, child$1.t, child$1.m, child$1.b, child$1.f);
}));
}

Expand All @@ -1301,7 +1301,9 @@ function factory$1(schema) {
return makeSchema(containerName, {
TAG: "Null",
_0: schema
}, empty, builder, maybeTypeFilter(schema, "null"), reverse$1);
}, empty, builder, maybeTypeFilter(schema, "null"), (function () {
return factory(schema.r());
}));
}

function nullable(schema) {
Expand Down Expand Up @@ -1477,7 +1479,7 @@ function name() {
}).join(", ") + "})";
}

function reverse$2() {
function reverse$1() {
var original = this;
return makeReverseSchema(primitiveName, "Unknown", empty, (function (b, input, param, path) {
var inputVar = $$var(b, input);
Expand Down Expand Up @@ -1621,7 +1623,7 @@ function factory$3(definer) {
definition: definition
},
n: name,
r: reverse$2,
r: reverse$1,
b: builder$2,
f: typeFilter$1,
i: 0,
Expand Down Expand Up @@ -1693,7 +1695,7 @@ function tuple(definer) {
definition: definition
}, empty, builder$2, (function (b, inputVar) {
return typeFilter(b, inputVar) + ("||" + inputVar + ".length!==" + length);
}), reverse$2);
}), reverse$1);
}

function variant(schema, definer) {
Expand Down
Loading

0 comments on commit 09d926a

Please sign in to comment.