diff options
author | Louis Pilfold <louis@lpil.uk> | 2022-01-01 23:27:58 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2022-01-01 23:27:58 +0000 |
commit | 9d40cdf444e0c73c192561658855f259cab6b507 (patch) | |
tree | e5caf8ed92dc4ae6cac4fda5d176e2d8117d118c | |
parent | 54d0699156d3d2ab7ac70c4099c7665381ba01b0 (diff) | |
download | gleam_stdlib-9d40cdf444e0c73c192561658855f259cab6b507.tar.gz gleam_stdlib-9d40cdf444e0c73c192561658855f259cab6b507.zip |
Tuple decoders set path
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/gleam/dynamic.gleam | 93 | ||||
-rw-r--r-- | test/gleam/dynamic_test.gleam | 10 |
3 files changed, 80 insertions, 25 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a74ee6a..85afcef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - The `dynamic.typed_tuple*` functions have been renamed to `dynamic.tuple*`. - The `dynamic.field` and `dynamic.element` functions now requires the type of the field to be specified. +- The `dynamic.DecodeError` now has a `path` field. +- The decoder functions of the `dynamic` module now return multiple errors. ## v0.18.1 - 2021-12-19 diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 81a7a92..9a626dc 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -530,8 +530,12 @@ pub fn tuple2( ) -> Result(#(a, b), DecodeErrors) { try _ = assert_is_tuple(value, 2) let #(first, second) = unsafe_coerce(value) - try a = decode_first(first) - try b = decode_second(second) + try a = + decode_first(first) + |> map_errors(push_path(_, "0")) + try b = + decode_second(second) + |> map_errors(push_path(_, "1")) Ok(#(a, b)) } @@ -556,6 +560,19 @@ fn put_expected(error: DecodeError, expected: String) -> DecodeError { DecodeError(..error, expected: expected) } +fn push_path(error: DecodeError, name: t) -> DecodeError { + let name = from(name) + let decoder = any(_, [string, fn(x) { result.map(int(x), int.to_string) }]) + let name = case decoder(name) { + Ok(name) -> name + Error(_) -> + ["<", classify(name), ">"] + |> string_builder.from_strings + |> string_builder.to_string + } + DecodeError(..error, path: [name, ..error.path]) +} + /// Checks to see if a `Dynamic` value is a 3-element tuple containing /// specifically typed elements. /// @@ -581,9 +598,15 @@ pub fn tuple3( ) -> Result(#(a, b, c), DecodeErrors) { try _ = assert_is_tuple(value, 3) let #(first, second, third) = unsafe_coerce(value) - try a = decode_first(first) - try b = decode_second(second) - try c = decode_third(third) + 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)) } @@ -614,10 +637,18 @@ pub fn tuple4( ) -> 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) - try b = decode_second(second) - try c = decode_third(third) - try d = decode_fourth(fourth) + 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)) } @@ -648,11 +679,21 @@ pub fn tuple5( ) -> 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) - try b = decode_second(second) - try c = decode_third(third) - try d = decode_fourth(fourth) - try e = decode_fifth(fifth) + 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)) } @@ -684,12 +725,24 @@ pub fn tuple6( ) -> 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) - try b = decode_second(second) - try c = decode_third(third) - try d = decode_fourth(fourth) - try e = decode_fifth(fifth) - try f = decode_sixth(sixth) + 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)) } diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam index f6622aa..7d490dc 100644 --- a/test/gleam/dynamic_test.gleam +++ b/test/gleam/dynamic_test.gleam @@ -380,7 +380,7 @@ pub fn tuple2_test() { |> dynamic.from |> dynamic.tuple2(dynamic.int, dynamic.int) |> should.equal(Error([ - DecodeError(expected: "Int", found: "String", path: []), + DecodeError(expected: "Int", found: "String", path: ["1"]), ])) #(1, 2, 3) @@ -417,7 +417,7 @@ pub fn tuple3_test() { |> dynamic.from |> dynamic.tuple3(dynamic.int, dynamic.int, dynamic.int) |> should.equal(Error([ - DecodeError(expected: "Int", found: "String", path: []), + DecodeError(expected: "Int", found: "String", path: ["2"]), ])) #(1, 2) @@ -454,7 +454,7 @@ pub fn tuple4_test() { |> dynamic.from |> dynamic.tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int) |> should.equal(Error([ - DecodeError(expected: "Int", found: "String", path: []), + DecodeError(expected: "Int", found: "String", path: ["3"]), ])) #(1, 2) @@ -509,7 +509,7 @@ pub fn tuple5_test() { dynamic.int, ) |> should.equal(Error([ - DecodeError(expected: "Int", found: "String", path: []), + DecodeError(expected: "Int", found: "String", path: ["4"]), ])) #(1, 2) @@ -579,7 +579,7 @@ pub fn tuple6_test() { dynamic.int, ) |> should.equal(Error([ - DecodeError(expected: "Int", found: "String", path: []), + DecodeError(expected: "Int", found: "String", path: ["5"]), ])) #(1, 2) |