aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/gleam/dynamic.gleam28
-rw-r--r--src/gleam/gleam_uri_native.erl27
-rw-r--r--src/gleam/uri.gleam48
-rw-r--r--src/gleam_stdlib.erl5
-rw-r--r--test/gleam/dynamic_test.gleam12
6 files changed, 76 insertions, 46 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ed6646..ba5202a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@
`ends_with`, `slice`, `pad_left` and `pad_right` functions.
- `uri` module created with `parse`, `parse_query`, `path_segments`,
`query_to_string` and `to_string`.
-- The `dynamic` module gains the `tuple2`, and `tuple2_of` functions.
+- The `dynamic` module gains the `map`, `tuple2`, and `tuple2_of` functions.
- The `list` module gains the `filter_map` function.
## v0.8.0 - 2020-04-28
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam
index e7e665d..89826ec 100644
--- a/src/gleam/dynamic.gleam
+++ b/src/gleam/dynamic.gleam
@@ -1,5 +1,6 @@
import gleam/list as list_mod
import gleam/atom
+import gleam/map.{Map}
import gleam/result
/// `Dynamic` data is data that we don"t know the type of yet.
@@ -167,7 +168,7 @@ pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, String) =
/// Error("Expected a tuple of at least 3 size, got a tuple of 2 size")
///
/// > element(from(""), 2)
-/// Error("Expected a Tuple, got a binary")
+/// Error("Expected a tuple, got a binary")
///
pub external fn element(
from: Dynamic,
@@ -186,7 +187,7 @@ pub external fn element(
/// Error("Expected a 2 element tuple")
///
/// > tuple2(from(""))
-/// Error("Expected a Tuple, got a binary")
+/// Error("Expected a tuple, got a binary")
///
pub external fn tuple2(
from: Dynamic,
@@ -204,11 +205,11 @@ pub external fn tuple2(
/// > tuple2_of(from(tuple(1, 2.0)), int, float)
/// Ok(tuple(1, 2.0))
///
-/// > tuple2_of(from(tuple(1, 2)), int, float)
-/// Error("Expected a 2 element tuple")
+/// > tuple2_of(from(tuple(1, 2, 3)), int, float)
+/// Error("Expected a 2 element tuple, got a 3 element tuple")
///
/// > tuple2_of(from(""), int, float)
-/// Error("Expected a Tuple, got a binary")
+/// Error("Expected a tuple, got a binary")
///
pub fn tuple2_of(
from tup: Dynamic,
@@ -232,3 +233,20 @@ pub fn tuple2_of(
},
)
}
+
+/// Check to see if the Dynamic value is map.
+///
+/// ## Examples
+///
+/// > import gleam/map as map_mod
+/// > map(from(map_mod.new()))
+/// Ok(map_mod.new())
+///
+/// > map(from(1))
+/// Error("Expected a 2 element tuple, got an int")
+///
+/// > map(from(""))
+/// Error("Expected a map, got a binary")
+///
+pub external fn map(from: Dynamic) -> Result(Map(Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_map"
diff --git a/src/gleam/gleam_uri_native.erl b/src/gleam/gleam_uri_native.erl
deleted file mode 100644
index dafd406..0000000
--- a/src/gleam/gleam_uri_native.erl
+++ /dev/null
@@ -1,27 +0,0 @@
--module (gleam_uri_native).
--export ([parse/1]).
-
-find_key(Key, Map) ->
- case maps:find(Key, Map) of
- {ok, Value} ->
- {ok, Value};
- error ->
- {error, nil}
- end.
-
-parse(String) ->
- case uri_string:parse(String) of
- {error, _Reason, _Term} ->
- {error, nil};
- Map ->
- {ok, {
- uri,
- find_key(scheme, Map),
- find_key(userinfo, Map),
- find_key(host, Map),
- find_key(port, Map),
- maps:get(path, Map),
- find_key(query, Map),
- find_key(fragment, Map)
- }}
- end.
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam
index a62cf3c..19feb27 100644
--- a/src/gleam/uri.gleam
+++ b/src/gleam/uri.gleam
@@ -28,13 +28,47 @@ pub type Uri {
)
}
+pub external fn erl_parse(String) -> Dynamic =
+ "uri_string" "parse"
+
+type UriKey {
+ Scheme
+ Userinfo
+ Host
+ Port
+ Path
+ Query
+ Fragment
+}
+
/// Parses a complient URI string into the `Uri` Type.
/// If the string is not a valid URI string then an error is returned.
///
/// The opposite operation is `uri.to_string`
///
-pub external fn parse(String) -> Result(Uri, Nil) =
- "gleam_uri_native" "parse"
+pub fn parse(string: String) -> Result(Uri, Nil) {
+ case dynamic.map(erl_parse(string)) {
+ Error(_) -> Error(Nil)
+ Ok(uri_map) -> {
+ let get = fn(k, decoder: dynamic.Decoder(t)) {
+ uri_map
+ |> map.get(dynamic.from(k))
+ |> result.then(fn(x) { result.map_error(decoder(x), fn(_) { Nil }) })
+ }
+
+ let uri = Uri(
+ scheme: get(Scheme, dynamic.string),
+ userinfo: get(Userinfo, dynamic.string),
+ host: get(Host, dynamic.string),
+ port: get(Port, dynamic.int),
+ path: result.unwrap(get(Path, dynamic.string), ""),
+ query: get(Query, dynamic.string),
+ fragment: get(Fragment, dynamic.string),
+ )
+ Ok(uri)
+ }
+ }
+}
external fn erl_parse_query(String) -> Dynamic =
"uri_string" "dissect_query"
@@ -101,16 +135,6 @@ pub fn path_segments(path) {
do_path_segments(string.split(path, "/"), [])
}
-type UriKey {
- Scheme
- Userinfo
- Host
- Port
- Path
- Query
- Fragment
-}
-
external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
"uri_string" "recompose"
diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl
index e12ee87..e78d60e 100644
--- a/src/gleam_stdlib.erl
+++ b/src/gleam_stdlib.erl
@@ -9,7 +9,7 @@
decode_thunk/1, decode_atom/1, decode_list/1, decode_field/2,
decode_element/2, parse_int/1, parse_float/1, compare_strings/2,
string_contains/2, string_starts_with/2, string_ends_with/2,
- string_pad/4, decode_tuple2/1]).
+ string_pad/4, decode_tuple2/1, decode_map/1]).
should_equal(Actual, Expected) -> ?assertEqual(Expected, Actual).
should_not_equal(Actual, Expected) -> ?assertNotEqual(Expected, Actual).
@@ -56,6 +56,9 @@ classify(_) -> "some other type".
decode_tuple2({_, _} = T) -> {ok, T};
decode_tuple2(Data) -> decode_error_msg("a 2 element tuple", Data).
+decode_map(Data) when is_map(Data) -> {ok, Data};
+decode_map(Data) -> decode_error_msg("a map", Data).
+
decode_atom(Data) when is_atom(Data) -> {ok, Data};
decode_atom(Data) -> decode_error_msg("an atom", Data).
diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam
index 4f314e9..5b5a88c 100644
--- a/test/gleam/dynamic_test.gleam
+++ b/test/gleam/dynamic_test.gleam
@@ -304,3 +304,15 @@ pub fn tuple2_of_test() {
|> dynamic.tuple2
|> should.equal(Error("Expected a 2 element tuple, got an int"))
}
+
+pub fn map_test() {
+ map.new()
+ |> dynamic.from
+ |> dynamic.map
+ |> should.equal(Ok(map.new()))
+
+ 1
+ |> dynamic.from
+ |> dynamic.map
+ |> should.equal(Error("Expected a map, got an int"))
+}