Skip to content

Commit

Permalink
new: int and bool union helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
mlms13 committed Mar 24, 2023
1 parent b6eae00 commit f2c7f5e
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 10 deletions.
16 changes: 16 additions & 0 deletions src/Decode_AsResult_OfParseError.rei
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,26 @@ let literal:
let literalString: (string, Js.Json.t) => result(string, ParseError.failure);
let literalInt: (int, Js.Json.t) => result(int, ParseError.failure);
let literalFloat: (float, Js.Json.t) => result(float, ParseError.failure);
let literalBool: (bool, Js.Json.t) => result(bool, ParseError.failure);
let literalTrue: Js.Json.t => result(bool, ParseError.failure);
let literalFalse: Js.Json.t => result(bool, ParseError.failure);

let union:
(
('a, Js.Json.t) => result('a, ParseError.failure),
('a, 'b),
list(('a, 'b)),
Js.Json.t
) =>
result('b, ParseError.failure);

let stringUnion:
((string, 'a), list((string, 'a)), Js.Json.t) =>
result('a, ParseError.failure);

let intUnion:
((int, 'a), list((int, 'a)), Js.Json.t) => result('a, ParseError.failure);

[@deprecated "Use literal instead"]
let variantFromJson:
(
Expand Down
14 changes: 12 additions & 2 deletions src/Decode_Base.re
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,21 @@ module Make =

let literalFloat = literal((==), floatFromNumber);

let stringUnion = (first, rest) => {
let mkDecode = ((s, v)) => literalString(s) |> map(_ => v);
let literalBool = literal((==), boolean);

let literalTrue = literalBool(true);

let literalFalse = literalBool(false);

let union = (decode, first, rest) => {
let mkDecode = ((s, v)) => decode(s) |> map(_ => v);
first |> mkDecode |> oneOf(_, rest |> List.map(mkDecode));
};

let stringUnion = first => union(literalString, first);

let intUnion = first => union(literalInt, first);

let variantFromJson = (jsonToJs, jsToVariant) =>
jsonToJs
|> map(jsToVariant)
Expand Down
8 changes: 4 additions & 4 deletions test/Decode_AsOption_test.re
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Sample = Decode_TestSampleData;

describe("Simple decoders", () => {
test("bool (success)", () =>
expect(Decode.boolean(Sample.jsonBool))
expect(Decode.boolean(Sample.jsonTrue))
|> toEqual(Some(Sample.valBool))
);

Expand Down Expand Up @@ -182,7 +182,7 @@ describe("Nested decoders", () => {
);

test("optional float (fails on bool)", () =>
expect(Decode.(optional(floatFromNumber, Sample.jsonBool)))
expect(Decode.(optional(floatFromNumber, Sample.jsonTrue)))
|> toEqual(None)
);

Expand Down Expand Up @@ -225,7 +225,7 @@ describe("Nested decoders", () => {
);

test("tuple2 (fails on non-array)", () =>
expect(Decode.(tuple(string, boolean, Sample.jsonBool)))
expect(Decode.(tuple(string, boolean, Sample.jsonTrue)))
|> toEqual(None)
);

Expand Down Expand Up @@ -429,7 +429,7 @@ describe("Decode with alternatives/fallbacks", () => {
);

test("oneOf (succeeds on last)", () =>
expect(decodeUnion(Sample.jsonBool))
expect(decodeUnion(Sample.jsonTrue))
|> toEqual(Some(Sample.(B(valBool))))
);

Expand Down
49 changes: 47 additions & 2 deletions test/Decode_AsResult_OfParseError_test.re
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let objErrSingle = (field, err) => objErr((field, err), []);
describe("Decode utils", () => {
test("hush (success)", () => {
let decodeBooleanOpt = Decode.(boolean |> hush);
expect(decodeBooleanOpt(Sample.jsonBool)) |> toEqual(Some(true));
expect(decodeBooleanOpt(Sample.jsonTrue)) |> toEqual(Some(true));
});

test("hush (failure)", () => {
Expand All @@ -27,6 +27,9 @@ describe("Decode utils", () => {
});

describe("Simple decoders", () => {
let decodeIntColor =
Decode.intUnion((0, `blue), [(1, `red), (2, `green)]);

test("boolean", () =>
expect(Decode.boolean(Sample.jsonNull))
|> toEqual(valErr(`ExpectedBoolean, Sample.jsonNull))
Expand Down Expand Up @@ -78,6 +81,48 @@ describe("Simple decoders", () => {
)
);

test("literalTrue (success)", () =>
expect(Decode.literalTrue(Sample.jsonTrue)) |> toEqual(Result.ok(true))
);

test("literalTrue (failure)", () =>
expect(Decode.literalTrue(Sample.jsonFalse))
|> toEqual(valErr(`ExpectedValidOption, Sample.jsonFalse))
);

test("literalFalse (success)", () =>
expect(Decode.literalFalse(Sample.jsonFalse))
|> toEqual(Result.ok(false))
);

test("literalFalse (failure)", () =>
expect(Decode.literalFalse(Sample.jsonTrue))
|> toEqual(valErr(`ExpectedValidOption, Sample.jsonTrue))
);

test("intUnion (success)", () =>
expect(decodeIntColor(Sample.jsonIntZero)) |> toEqual(Result.ok(`blue))
);

test("intUnion (failure)", () =>
expect(decodeIntColor(Sample.jsonIntFive))
|> toEqual(
Result.error(
Decode.ParseError.(
TriedMultiple(
NonEmpty.List.make(
Val(`ExpectedValidOption, Sample.jsonIntFive),
[
Val(`ExpectedValidOption, Sample.jsonIntFive),
Val(`ExpectedValidOption, Sample.jsonIntFive),
],
),
)
),
),
)
);

test("variant", () =>
[@ocaml.warning "-3"]
expect(Decode.variantFromString(Sample.colorFromJs, Sample.jsonString))
Expand Down Expand Up @@ -181,7 +226,7 @@ describe("Inner decoders", () => {
);

test("oneOf (success on last)", () =>
expect(decodeUnion(Sample.jsonBool))
expect(decodeUnion(Sample.jsonTrue))
|> toEqual(Result.ok(Sample.B(Sample.valBool)))
);

Expand Down
2 changes: 1 addition & 1 deletion test/Decode_AsResult_OfStringNel_test.re
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe("Inner decoders", () => {
)
);

expect(decodeUnion(Sample.jsonBool))
expect(decodeUnion(Sample.jsonTrue))
|> toEqual(Result.ok(Sample.(B(valBool))));
});
});
3 changes: 2 additions & 1 deletion test/utils/Decode_TestSampleData.re
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Simple JSON values
let jsonNull: Js.Json.t = [%raw {| null |}];
let jsonBool: Js.Json.t = [%raw {| true |}];
let jsonTrue: Js.Json.t = [%raw {| true |}];
let jsonFalse: Js.Json.t = [%raw {| false |}];
let jsonString: Js.Json.t = [%raw {| "string" |}];
let jsonStringTrue: Js.Json.t = [%raw {| "true" |}];
let jsonString4: Js.Json.t = [%raw {| "4" |}];
Expand Down

0 comments on commit f2c7f5e

Please sign in to comment.