aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gleam/dynamic.gleam49
-rw-r--r--src/gleam_stdlib.erl3
-rw-r--r--src/gleam_stdlib.js26
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));
+ }
+ }
+}