diff options
author | Louis Pilfold <louis@lpil.uk> | 2021-09-11 14:56:20 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2021-09-11 14:56:20 +0100 |
commit | ff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0 (patch) | |
tree | 740d47b3b2e93545fbddc7fd6858517f4092aa71 | |
parent | a6b75f614c97f7cf2bede89b5769bfcd13c31571 (diff) | |
download | gleam_stdlib-ff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0.tar.gz gleam_stdlib-ff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0.zip |
JS decode field for objects
-rw-r--r-- | src/gleam/dynamic.gleam | 39 | ||||
-rw-r--r-- | src/gleam_stdlib.erl | 2 | ||||
-rw-r--r-- | src/gleam_stdlib.js | 8 | ||||
-rw-r--r-- | test/gleam/dynamic_test.gleam | 22 |
4 files changed, 55 insertions, 16 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 2175461..8caa858 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -382,25 +382,34 @@ if javascript { "../gleam_stdlib.js" "decode_option" } +/// Checks to see if a Dynamic value is a map with a specific field, and return +/// the value of the field if it is. +/// +/// This will not succeed on a record. +/// +/// ## Examples +/// +/// > import gleam/map +/// > field(from(map.new("Hello", "World")), "Hello") +/// Ok(Dynamic) +/// +/// > field(from(123), "Hello") +/// Error(DecodeError(expected: "Map", found: "Int")) +/// +pub fn field(from value: Dynamic, named name: a) -> Result(Dynamic, DecodeError) { + decode_field(value, name) +} + if erlang { - /// Checks to see if a Dynamic value is a map with a specific field, and return - /// the value of the field if it is. - /// - /// This will not succeed on a record. - /// - /// ## Examples - /// - /// > import gleam/map - /// > field(from(map.new("Hello", "World")), "Hello") - /// Ok(Dynamic) - /// - /// > field(from(123), "Hello") - /// Error(DecodeError(expected: "Map", found: "Int")) - /// - pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, DecodeError) = + external fn decode_field(Dynamic, name) -> Result(Dynamic, DecodeError) = "gleam_stdlib" "decode_field" } +if javascript { + external fn decode_field(Dynamic, name) -> Result(Dynamic, DecodeError) = + "../gleam_stdlib.js" "decode_field" +} + /// Checks to see if the Dynamic value is a tuple large enough to have a certain /// index, and return the value of that index if it is. /// diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index c901499..4c8a428 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -94,7 +94,7 @@ decode_list(Data) -> decode_error_msg(<<"List">>, Data). decode_field(Data, Key) -> case Data of #{Key := Value} -> {ok, Value}; - _ -> decode_error_msg(io_lib:format("a map with key `~p`", [Key]), Data) + _ -> decode_error_msg(io_lib:format("Value with field `~p`", [Key]), Data) end. size_of_tuple(Data) -> tuple_size(Data). diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js index 37f071a..b7173c2 100644 --- a/src/gleam_stdlib.js +++ b/src/gleam_stdlib.js @@ -473,6 +473,8 @@ export function decode64(sBase64) { export function classify_dynamic(data) { if (typeof data === "string") { return "String"; + } else if (Result.isResult(data)) { + return "Result"; } else if (List.isList(data)) { return "List"; } else if (Number.isInteger(data)) { @@ -552,3 +554,9 @@ export function decode_option(data, decoder) { return result; } } + +export function decode_field(value, name) { + return name in value + ? new Ok(value[name]) + : decoder_error(`Value with field ${inspect(name)}`, value); +} diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam index c062d91..ae3285b 100644 --- a/test/gleam/dynamic_test.gleam +++ b/test/gleam/dynamic_test.gleam @@ -224,6 +224,28 @@ pub fn optional_test() { |> should.be_error } +if javascript { + pub fn javascript_object_field_test() { + Ok(123) + |> dynamic.from + |> dynamic.field("0") + |> should.equal(Ok(dynamic.from(123))) + + Ok(123) + |> dynamic.from + |> dynamic.field(0) + |> should.equal(Ok(dynamic.from(123))) + + Ok(123) + |> dynamic.from + |> dynamic.field("Nope") + |> should.equal(Error(DecodeError( + expected: "Value with field \"Nope\"", + found: "Result", + ))) + } +} + if erlang { pub fn field_test() { map.new() |