aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrew <drew@drewolson.org>2020-11-03 12:57:08 -0600
committerLouis Pilfold <louis@lpil.uk>2020-11-07 19:16:29 +0000
commit8254bd1079512ed8c8ae8d6fe3c1daf339e4e39e (patch)
treed0ba1c164719abb2d992c678929378eb0ac00ff8 /src
parentc1d3cc12b920f60d06265b645daa3ff0010a8402 (diff)
downloadgleam_stdlib-8254bd1079512ed8c8ae8d6fe3c1daf339e4e39e.tar.gz
gleam_stdlib-8254bd1079512ed8c8ae8d6fe3c1daf339e4e39e.zip
Add result and typed_result to dynamic
Diffstat (limited to 'src')
-rw-r--r--src/gleam/dynamic.gleam81
1 files changed, 76 insertions, 5 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam
index e4656c4..e4b67b6 100644
--- a/src/gleam/dynamic.gleam
+++ b/src/gleam/dynamic.gleam
@@ -1,9 +1,10 @@
+import gleam/atom as atom_mod
import gleam/bit_string.{BitString} as bit_string_mod
import gleam/list as list_mod
-import gleam/atom as atom_mod
import gleam/map.{Map}
-import gleam/result
import gleam/option.{None, Option, Some}
+import gleam/result as result_mod
+import gleam/string_builder
/// `Dynamic` data is data that we don"t know the type of yet.
/// We likely get data like this from interop with Erlang, or from
@@ -55,7 +56,7 @@ pub external fn bit_string(from: Dynamic) -> Result(BitString, String) =
///
pub fn string(from: Dynamic) -> Result(String, String) {
bit_string(from)
- |> result.then(fn(raw) {
+ |> result_mod.then(fn(raw) {
case bit_string_mod.to_string(raw) {
Ok(string) -> Ok(string)
Error(Nil) -> Error("Expected a string, got a bit_string")
@@ -153,6 +154,76 @@ pub external fn thunk(from: Dynamic) -> Result(fn() -> Dynamic, String) =
pub external fn list(from: Dynamic) -> Result(List(Dynamic), String) =
"gleam_stdlib" "decode_list"
+/// Check to see whether a Dynamic value is a result, and return the result if
+/// it is
+///
+/// ## Examples
+///
+/// > result(from(Ok(1)))
+/// Ok(Ok(from(1)))
+///
+/// > result(from(Error("boom")))
+/// Ok(Error(from("boom")))
+///
+/// > result(from(123))
+/// Error("Expected a 2 element tuple, got an int")
+///
+pub fn result(from: Dynamic) -> Result(Result(Dynamic, Dynamic), String) {
+ try tuple(key, val) = tuple2(from)
+ try tag = atom(key)
+
+ let ok_atom = atom_mod.create_from_string("ok")
+ let error_atom = atom_mod.create_from_string("error")
+
+ case tag {
+ tag if tag == ok_atom -> Ok(Ok(val))
+ tag if tag == error_atom -> Ok(Error(val))
+ tag ->
+ "Expected a tag of \"ok\" or \"error\", got \""
+ |> string_builder.from_string
+ |> string_builder.append(atom_mod.to_string(tag))
+ |> string_builder.append("\"")
+ |> string_builder.to_string
+ |> Error
+ }
+}
+
+/// Check to see whether a Dynamic value is a result of a particular type, and
+/// return the result if it is
+///
+/// The `ok` and `error` arguments are decoders for decoding the `Ok` and
+/// `Error` values of the result.
+///
+/// ## Examples
+///
+/// > typed_result(of: from(Ok(1)), ok: int, error: string)
+/// Ok(Ok(1))
+///
+/// > typed_result(of: from(Error("boom")), ok: int, error: string)
+/// Ok(Error("boom"))
+///
+/// > typed_result(of: from(123), ok: int, error: string)
+/// Error("Expected a 2 element tuple, got an int")
+///
+pub fn typed_result(
+ of dynamic: Dynamic,
+ ok decode_ok: Decoder(a),
+ error decode_error: Decoder(e),
+) -> Result(Result(a, e), String) {
+ try inner_result = result(dynamic)
+
+ case inner_result {
+ Ok(raw) ->
+ raw
+ |> decode_ok
+ |> result_mod.map(Ok)
+ Error(raw) ->
+ raw
+ |> decode_error
+ |> result_mod.map(Error)
+ }
+}
+
/// Check to see whether a Dynamic value is a list of a particular type, and
/// return the list if it is.
///
@@ -180,7 +251,7 @@ pub fn typed_list(
) -> Result(List(inner), String) {
dynamic
|> list
- |> result.then(list_mod.try_map(_, decoder_type))
+ |> result_mod.then(list_mod.try_map(_, decoder_type))
}
/// Check to see if a Dynamic value is an Option of a particular type, and return
@@ -339,5 +410,5 @@ pub fn any(
) -> Result(t, String) {
decoders
|> list_mod.find_map(fn(decoder) { decoder(data) })
- |> result.map_error(fn(_) { "Unexpected value" })
+ |> result_mod.map_error(fn(_) { "Unexpected value" })
}