aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2022-01-03 14:27:56 +0000
committerLouis Pilfold <louis@lpil.uk>2022-01-03 14:27:56 +0000
commitc85007c3b8c1456220c81848f232664aa0c12e4d (patch)
treefed4710ab9e309e0b55370d54a2a5b405f89d904
parent492c92493013415467155788aebac6018f67c072 (diff)
downloadgleam_stdlib-c85007c3b8c1456220c81848f232664aa0c12e4d.tar.gz
gleam_stdlib-c85007c3b8c1456220c81848f232664aa0c12e4d.zip
Return all errors from tuple decoders
-rw-r--r--src/gleam/dynamic.gleam170
-rw-r--r--test/gleam/dynamic_test.gleam63
2 files changed, 143 insertions, 90 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam
index 57cc7b5..ff6045d 100644
--- a/src/gleam/dynamic.gleam
+++ b/src/gleam/dynamic.gleam
@@ -528,18 +528,28 @@ if javascript {
///
pub fn tuple2(
from value: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
+ first decode1: Decoder(a),
+ second decode2: Decoder(b),
) -> Result(#(a, b), DecodeErrors) {
try _ = assert_is_tuple(value, 2)
- let #(first, second) = unsafe_coerce(value)
- try a =
- decode_first(first)
- |> map_errors(push_path(_, "0"))
- try b =
- decode_second(second)
- |> map_errors(push_path(_, "1"))
- Ok(#(a, b))
+ let #(a, b) = unsafe_coerce(value)
+ case decode1(a), decode2(b) {
+ Ok(a), Ok(b) -> Ok(#(a, b))
+ a, b ->
+ tuple_errors(a, "0")
+ |> list.append(tuple_errors(b, "1"))
+ |> Error
+ }
+}
+
+fn tuple_errors(
+ result: Result(a, List(DecodeError)),
+ name: String,
+) -> List(DecodeError) {
+ case result {
+ Ok(_) -> []
+ Error(errors) -> list.map(errors, push_path(_, name))
+ }
}
fn assert_is_tuple(
@@ -595,22 +605,20 @@ fn push_path(error: DecodeError, name: t) -> DecodeError {
///
pub fn tuple3(
from value: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
+ first decode1: Decoder(a),
+ second decode2: Decoder(b),
+ third decode3: Decoder(c),
) -> Result(#(a, b, c), DecodeErrors) {
try _ = assert_is_tuple(value, 3)
- let #(first, second, third) = unsafe_coerce(value)
- try a =
- decode_first(first)
- |> map_errors(push_path(_, "0"))
- try b =
- decode_second(second)
- |> map_errors(push_path(_, "1"))
- try c =
- decode_third(third)
- |> map_errors(push_path(_, "2"))
- Ok(#(a, b, c))
+ let #(a, b, c) = unsafe_coerce(value)
+ case decode1(a), decode2(b), decode3(c) {
+ Ok(a), Ok(b), Ok(c) -> Ok(#(a, b, c))
+ a, b, c ->
+ tuple_errors(a, "0")
+ |> list.append(tuple_errors(b, "1"))
+ |> list.append(tuple_errors(c, "2"))
+ |> Error
+ }
}
/// Checks to see if a `Dynamic` value is a 4 element tuple containing
@@ -633,26 +641,22 @@ pub fn tuple3(
///
pub fn tuple4(
from value: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
+ first decode1: Decoder(a),
+ second decode2: Decoder(b),
+ third decode3: Decoder(c),
+ fourth decode4: Decoder(d),
) -> Result(#(a, b, c, d), DecodeErrors) {
try _ = assert_is_tuple(value, 4)
- let #(first, second, third, fourth) = unsafe_coerce(value)
- try a =
- decode_first(first)
- |> map_errors(push_path(_, "0"))
- try b =
- decode_second(second)
- |> map_errors(push_path(_, "1"))
- try c =
- decode_third(third)
- |> map_errors(push_path(_, "2"))
- try d =
- decode_fourth(fourth)
- |> map_errors(push_path(_, "3"))
- Ok(#(a, b, c, d))
+ let #(a, b, c, d) = unsafe_coerce(value)
+ case decode1(a), decode2(b), decode3(c), decode4(d) {
+ Ok(a), Ok(b), Ok(c), Ok(d) -> Ok(#(a, b, c, d))
+ a, b, c, d ->
+ tuple_errors(a, "0")
+ |> list.append(tuple_errors(b, "1"))
+ |> list.append(tuple_errors(c, "2"))
+ |> list.append(tuple_errors(d, "3"))
+ |> Error
+ }
}
/// Checks to see if a `Dynamic` value is a 5-element tuple containing
@@ -674,30 +678,24 @@ pub fn tuple4(
///
pub fn tuple5(
from value: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
- fifth decode_fifth: Decoder(e),
+ first decode1: Decoder(a),
+ second decode2: Decoder(b),
+ third decode3: Decoder(c),
+ fourth decode4: Decoder(d),
+ fifth decode5: Decoder(e),
) -> Result(#(a, b, c, d, e), DecodeErrors) {
try _ = assert_is_tuple(value, 5)
- let #(first, second, third, fourth, fifth) = unsafe_coerce(value)
- try a =
- decode_first(first)
- |> map_errors(push_path(_, "0"))
- try b =
- decode_second(second)
- |> map_errors(push_path(_, "1"))
- try c =
- decode_third(third)
- |> map_errors(push_path(_, "2"))
- try d =
- decode_fourth(fourth)
- |> map_errors(push_path(_, "3"))
- try e =
- decode_fifth(fifth)
- |> map_errors(push_path(_, "4"))
- Ok(#(a, b, c, d, e))
+ let #(a, b, c, d, e) = unsafe_coerce(value)
+ case decode1(a), decode2(b), decode3(c), decode4(d), decode5(e) {
+ Ok(a), Ok(b), Ok(c), Ok(d), Ok(e) -> Ok(#(a, b, c, d, e))
+ a, b, c, d, e ->
+ tuple_errors(a, "0")
+ |> list.append(tuple_errors(b, "1"))
+ |> list.append(tuple_errors(c, "2"))
+ |> list.append(tuple_errors(d, "3"))
+ |> list.append(tuple_errors(e, "4"))
+ |> Error
+ }
}
/// Checks to see if a `Dynamic` value is a 6-element tuple containing
@@ -719,34 +717,26 @@ pub fn tuple5(
///
pub fn tuple6(
from value: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
- fifth decode_fifth: Decoder(e),
- sixth decode_sixth: Decoder(f),
+ first decode1: Decoder(a),
+ second decode2: Decoder(b),
+ third decode3: Decoder(c),
+ fourth decode4: Decoder(d),
+ fifth decode5: Decoder(e),
+ sixth decode6: Decoder(f),
) -> Result(#(a, b, c, d, e, f), DecodeErrors) {
try _ = assert_is_tuple(value, 6)
- let #(first, second, third, fourth, fifth, sixth) = unsafe_coerce(value)
- try a =
- decode_first(first)
- |> map_errors(push_path(_, "0"))
- try b =
- decode_second(second)
- |> map_errors(push_path(_, "1"))
- try c =
- decode_third(third)
- |> map_errors(push_path(_, "2"))
- try d =
- decode_fourth(fourth)
- |> map_errors(push_path(_, "3"))
- try e =
- decode_fifth(fifth)
- |> map_errors(push_path(_, "4"))
- try f =
- decode_sixth(sixth)
- |> map_errors(push_path(_, "5"))
- Ok(#(a, b, c, d, e, f))
+ let #(a, b, c, d, e, f) = unsafe_coerce(value)
+ case decode1(a), decode2(b), decode3(c), decode4(d), decode5(e), decode6(f) {
+ Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f) -> Ok(#(a, b, c, d, e, f))
+ a, b, c, d, e, f ->
+ tuple_errors(a, "0")
+ |> list.append(tuple_errors(b, "1"))
+ |> list.append(tuple_errors(c, "2"))
+ |> list.append(tuple_errors(d, "3"))
+ |> list.append(tuple_errors(e, "4"))
+ |> list.append(tuple_errors(f, "5"))
+ |> Error
+ }
}
/// Checks to see if a `Dynamic` value is a map.
diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam
index 8f2a54d..64f1aac 100644
--- a/test/gleam/dynamic_test.gleam
+++ b/test/gleam/dynamic_test.gleam
@@ -389,6 +389,14 @@ pub fn tuple2_test() {
DecodeError(expected: "Int", found: "String", path: ["1"]),
]))
+ #(1.2, "")
+ |> dynamic.from
+ |> dynamic.tuple2(dynamic.int, dynamic.int)
+ |> should.equal(Error([
+ DecodeError(expected: "Int", found: "Float", path: ["0"]),
+ DecodeError(expected: "Int", found: "String", path: ["1"]),
+ ]))
+
#(1, 2, 3)
|> dynamic.from
|> dynamic.tuple2(dynamic.int, dynamic.int)
@@ -426,6 +434,15 @@ pub fn tuple3_test() {
DecodeError(expected: "Int", found: "String", path: ["2"]),
]))
+ #(1.2, "", "")
+ |> dynamic.from
+ |> dynamic.tuple3(dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error([
+ DecodeError(expected: "Int", found: "Float", path: ["0"]),
+ DecodeError(expected: "Int", found: "String", path: ["1"]),
+ DecodeError(expected: "Int", found: "String", path: ["2"]),
+ ]))
+
#(1, 2)
|> dynamic.from
|> dynamic.tuple3(dynamic.int, dynamic.int, dynamic.int)
@@ -463,6 +480,16 @@ pub fn tuple4_test() {
DecodeError(expected: "Int", found: "String", path: ["3"]),
]))
+ #(1.2, "", "", "")
+ |> dynamic.from
+ |> dynamic.tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error([
+ DecodeError(expected: "Int", found: "Float", path: ["0"]),
+ DecodeError(expected: "Int", found: "String", path: ["1"]),
+ DecodeError(expected: "Int", found: "String", path: ["2"]),
+ DecodeError(expected: "Int", found: "String", path: ["3"]),
+ ]))
+
#(1, 2)
|> dynamic.from
|> dynamic.tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
@@ -518,6 +545,23 @@ pub fn tuple5_test() {
DecodeError(expected: "Int", found: "String", path: ["4"]),
]))
+ #(1.2, "", "", "", "")
+ |> dynamic.from
+ |> dynamic.tuple5(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error([
+ DecodeError(expected: "Int", found: "Float", path: ["0"]),
+ DecodeError(expected: "Int", found: "String", path: ["1"]),
+ DecodeError(expected: "Int", found: "String", path: ["2"]),
+ DecodeError(expected: "Int", found: "String", path: ["3"]),
+ DecodeError(expected: "Int", found: "String", path: ["4"]),
+ ]))
+
#(1, 2)
|> dynamic.from
|> dynamic.tuple5(
@@ -588,6 +632,25 @@ pub fn tuple6_test() {
DecodeError(expected: "Int", found: "String", path: ["5"]),
]))
+ #(1.2, "", "", "", "", "")
+ |> dynamic.from
+ |> dynamic.tuple6(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error([
+ DecodeError(expected: "Int", found: "Float", path: ["0"]),
+ DecodeError(expected: "Int", found: "String", path: ["1"]),
+ DecodeError(expected: "Int", found: "String", path: ["2"]),
+ DecodeError(expected: "Int", found: "String", path: ["3"]),
+ DecodeError(expected: "Int", found: "String", path: ["4"]),
+ DecodeError(expected: "Int", found: "String", path: ["5"]),
+ ]))
+
#(1, 2)
|> dynamic.from
|> dynamic.tuple6(