diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gleam/dynamic.gleam | 49 | ||||
-rw-r--r-- | src/gleam_stdlib.erl | 3 | ||||
-rw-r--r-- | src/gleam_stdlib.js | 26 |
3 files changed, 59 insertions, 19 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 903341a..d494550 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -341,27 +341,40 @@ if erlang { /// pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, DecodeError) = "gleam_stdlib" "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. - /// - /// ## Examples - /// - /// > element(from(#(1, 2)), 0) - /// Ok(from(1)) - /// - /// > element(from(#(1, 2)), 2) - /// Error(DecodeError(expected: "3 element tuple", found: "2 element tuple")) - /// - /// > element(from(""), 2) - /// Error(DecodeError(expected: "Tuple", found: "String")) - /// - pub external fn element( - from: Dynamic, - position: Int, - ) -> Result(Dynamic, DecodeError) = +/// 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. +/// +/// ## Examples +/// +/// > element(from(#(1, 2)), 0) +/// Ok(from(1)) +/// +/// > element(from(#(1, 2)), 2) +/// Error(DecodeError(expected: "3 element tuple", found: "2 element tuple")) +/// +/// > element(from(""), 2) +/// Error(DecodeError(expected: "Tuple", found: "String")) +/// +pub fn element( + from data: Dynamic, + get index: Int, +) -> Result(Dynamic, DecodeError) { + decode_element(data, index) +} + +if erlang { + external fn decode_element(Dynamic, Int) -> Result(a, DecodeError) = "gleam_stdlib" "decode_element" +} +if javascript { + external fn decode_element(Dynamic, Int) -> Result(a, DecodeError) = + "../gleam_stdlib.js" "decode_element" +} + +if erlang { /// Checks to see if the Dynamic value is a 2 element tuple. /// /// If you do not wish to decode all the elements in the tuple use the diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index 9429f71..92cae8e 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -111,7 +111,8 @@ decode_field(Data, Key) -> decode_element(Data, Position) when is_tuple(Data) -> case catch element(Position + 1, Data) of {'EXIT', _Reason} -> - decode_error_msg(["a tuple of at least ", integer_to_list(Position + 1), " size"], Data); + Msg = ["Tuple of at least ", integer_to_list(Position + 1), " elements"], + decode_error_msg(list_to_binary(Msg), Data); Value -> {ok, Value} diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js index 0982f62..9a80a6d 100644 --- a/src/gleam_stdlib.js +++ b/src/gleam_stdlib.js @@ -476,8 +476,12 @@ function classify_dynamic(data) { return "List"; } else if (Number.isInteger(data)) { return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; } else if (BitString.isBitString(data)) { return "BitString"; + } else if (data instanceof Map) { + return "Map"; } else if (typeof data === "number") { return "Float"; } else { @@ -513,3 +517,25 @@ export function decode_bit_string(data) { ? new Ok(data) : decoder_error("BitString", data); } + +export function decode_element(data, index) { + let error = (size) => + decoder_error( + `Tuple of at least ${size} element${size > 1 ? "s" : ""}`, + data + ); + if (!Array.isArray(data)) return error(index < 0 ? 1 : index + 1); + if (index >= 0) { + if (index < data.length) { + return new Ok(data[index]); + } else { + return error(index + 1); + } + } else { + if (Math.abs(index) <= data.length) { + return new Ok(data[data.length + index]); + } else { + return error(Math.abs(index)); + } + } +} |