aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-09-11 14:56:20 +0100
committerLouis Pilfold <louis@lpil.uk>2021-09-11 14:56:20 +0100
commitff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0 (patch)
tree740d47b3b2e93545fbddc7fd6858517f4092aa71
parenta6b75f614c97f7cf2bede89b5769bfcd13c31571 (diff)
downloadgleam_stdlib-ff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0.tar.gz
gleam_stdlib-ff8be8c4e25220e1fae4bbb4cbd20d1f2072aae0.zip
JS decode field for objects
-rw-r--r--src/gleam/dynamic.gleam39
-rw-r--r--src/gleam_stdlib.erl2
-rw-r--r--src/gleam_stdlib.js8
-rw-r--r--test/gleam/dynamic_test.gleam22
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()