create-mendix-widget-gleam 2.0.14 → 2.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +5 -1
- package/src/index.mjs +32 -12
- package/template/gleam.toml +1 -1
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/etch/command.mjs +479 -0
- package/tui/build/dev/javascript/etch/etch/cursor.mjs +164 -0
- package/tui/build/dev/javascript/etch/etch/event.mjs +2399 -0
- package/tui/build/dev/javascript/etch/etch/internal/consts.mjs +3 -0
- package/tui/build/dev/javascript/etch/etch/stdout.mjs +375 -0
- package/tui/build/dev/javascript/etch/etch/style.mjs +741 -0
- package/tui/build/dev/javascript/etch/etch/terminal.mjs +137 -0
- package/tui/build/dev/javascript/etch/gleam.mjs +1 -0
- package/tui/build/dev/javascript/etch/input/event_ffi.erl +73 -0
- package/tui/build/dev/javascript/etch/input/input_ffi.mjs +192 -0
- package/tui/build/dev/javascript/etch/input/signal_handler.erl +33 -0
- package/tui/build/dev/javascript/etch/terminal/terminal_ffi.erl +22 -0
- package/tui/build/dev/javascript/etch/terminal/terminal_ffi.mjs +37 -0
- package/tui/build/dev/javascript/etch/terminal/tty_state.erl +29 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/application.mjs +38 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/atom.mjs +2 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/charlist.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/node.mjs +12 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/port.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/process.mjs +161 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/reference.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@application.erl +43 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@atom.erl +94 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@charlist.erl +42 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@node.erl +80 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@port.erl +8 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@process.erl +868 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@reference.erl +21 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam_erlang_ffi.erl +164 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/array.mjs +24 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/promise.mjs +105 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/symbol.mjs +7 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam_javascript_ffi.mjs +133 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/dict.mjs +710 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs +286 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bool.mjs +295 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs +225 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dict.mjs +455 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs +993 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs +35 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/float.mjs +528 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/function.mjs +6 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/int.mjs +764 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/io.mjs +8 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/list.mjs +3063 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/option.mjs +386 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/order.mjs +166 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/pair.mjs +96 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/result.mjs +448 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/set.mjs +413 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/string.mjs +695 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs +128 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/uri.mjs +1151 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bit_array.erl +347 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bool.erl +334 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl +211 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dict.erl +513 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dynamic.erl +105 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl +1114 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@float.erl +711 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@function.erl +18 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@int.erl +972 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@io.erl +76 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@list.erl +2735 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@option.erl +381 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@order.erl +188 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@pair.erl +104 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@result.erl +500 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@set.erl +430 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@string.erl +964 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@string_tree.erl +202 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@uri.erl +1042 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam_stdlib.erl +534 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs +1133 -0
- package/tui/build/dev/javascript/gleam_version +1 -0
- package/tui/build/dev/javascript/prelude.mjs +1575 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_inline +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_meta +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_warnings +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_inline +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_meta +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_warnings +0 -0
- package/tui/build/dev/javascript/tui/gleam.mjs +1 -0
- package/tui/build/dev/javascript/tui/tui/prompt.mjs +521 -0
- package/tui/build/dev/javascript/tui/tui.mjs +334 -0
- package/tui/build/dev/javascript/tui/tui_ffi.mjs +32 -0
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
-module(gleam@dynamic@decode).
|
|
2
|
+
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
|
3
|
+
-define(FILEPATH, "src/gleam/dynamic/decode.gleam").
|
|
4
|
+
-export([run/2, success/1, decode_dynamic/1, map/2, map_errors/2, then/2, one_of/2, recursive/1, optional/1, decode_error/2, decode_bool/1, decode_int/1, decode_float/1, decode_bit_array/1, collapse_errors/2, failure/2, new_primitive_decoder/2, decode_string/1, dict/2, list/1, subfield/3, at/2, field/3, optional_field/4, optionally_at/3]).
|
|
5
|
+
-export_type([decode_error/0, decoder/1]).
|
|
6
|
+
|
|
7
|
+
-if(?OTP_RELEASE >= 27).
|
|
8
|
+
-define(MODULEDOC(Str), -moduledoc(Str)).
|
|
9
|
+
-define(DOC(Str), -doc(Str)).
|
|
10
|
+
-else.
|
|
11
|
+
-define(MODULEDOC(Str), -compile([])).
|
|
12
|
+
-define(DOC(Str), -compile([])).
|
|
13
|
+
-endif.
|
|
14
|
+
|
|
15
|
+
?MODULEDOC(
|
|
16
|
+
" The `Dynamic` type is used to represent dynamically typed data. That is, data\n"
|
|
17
|
+
" that we don't know the precise type of yet, so we need to introspect the data to\n"
|
|
18
|
+
" see if it is of the desired type before we can use it. Typically data like this\n"
|
|
19
|
+
" would come from user input or from untyped languages such as Erlang or JavaScript.\n"
|
|
20
|
+
"\n"
|
|
21
|
+
" This module provides the `Decoder` type and associated functions, which provides\n"
|
|
22
|
+
" a type-safe and composable way to convert dynamic data into some desired type,\n"
|
|
23
|
+
" or into errors if the data doesn't have the desired structure.\n"
|
|
24
|
+
"\n"
|
|
25
|
+
" The `Decoder` type is generic and has 1 type parameter, which is the type that\n"
|
|
26
|
+
" it attempts to decode. A `Decoder(String)` can be used to decode strings, and a\n"
|
|
27
|
+
" `Decoder(Option(Int))` can be used to decode `Option(Int)`s\n"
|
|
28
|
+
"\n"
|
|
29
|
+
" Decoders work using _runtime reflection_ and the data structures of the target\n"
|
|
30
|
+
" platform. Differences between Erlang and JavaScript data structures may impact\n"
|
|
31
|
+
" your decoders, so it is important to test your decoders on all supported\n"
|
|
32
|
+
" platforms.\n"
|
|
33
|
+
"\n"
|
|
34
|
+
" The decoding technique used by this module was inspired by Juraj Petráš'\n"
|
|
35
|
+
" [Toy](https://github.com/Hackder/toy), Go's `encoding/json`, and Elm's\n"
|
|
36
|
+
" `Json.Decode`. Thank you to them!\n"
|
|
37
|
+
"\n"
|
|
38
|
+
" # Examples\n"
|
|
39
|
+
"\n"
|
|
40
|
+
" Dynamic data may come from various sources and so many different syntaxes could\n"
|
|
41
|
+
" be used to describe or construct them. In these examples a pseudocode\n"
|
|
42
|
+
" syntax is used to describe the data.\n"
|
|
43
|
+
"\n"
|
|
44
|
+
" ## Simple types\n"
|
|
45
|
+
"\n"
|
|
46
|
+
" This module defines decoders for simple data types such as [`string`](#string),\n"
|
|
47
|
+
" [`int`](#int), [`float`](#float), [`bit_array`](#bit_array), and [`bool`](#bool).\n"
|
|
48
|
+
"\n"
|
|
49
|
+
" ```gleam\n"
|
|
50
|
+
" // Data:\n"
|
|
51
|
+
" // \"Hello, Joe!\"\n"
|
|
52
|
+
"\n"
|
|
53
|
+
" let result = decode.run(data, decode.string)\n"
|
|
54
|
+
" assert result == Ok(\"Hello, Joe!\")\n"
|
|
55
|
+
" ```\n"
|
|
56
|
+
"\n"
|
|
57
|
+
" ## Lists\n"
|
|
58
|
+
"\n"
|
|
59
|
+
" The [`list`](#list) decoder decodes `List`s. To use it you must construct it by\n"
|
|
60
|
+
" passing in another decoder into the `list` function, which is the decoder that\n"
|
|
61
|
+
" is to be used for the elements of the list, type checking both the list and its\n"
|
|
62
|
+
" elements.\n"
|
|
63
|
+
"\n"
|
|
64
|
+
" ```gleam\n"
|
|
65
|
+
" // Data:\n"
|
|
66
|
+
" // [1, 2, 3, 4]\n"
|
|
67
|
+
"\n"
|
|
68
|
+
" let result = decode.run(data, decode.list(decode.int))\n"
|
|
69
|
+
" assert result == Ok([1, 2, 3, 4])\n"
|
|
70
|
+
" ```\n"
|
|
71
|
+
"\n"
|
|
72
|
+
" On Erlang this decoder can decode from lists, and on JavaScript it can\n"
|
|
73
|
+
" decode from lists as well as JavaScript arrays.\n"
|
|
74
|
+
"\n"
|
|
75
|
+
" ## Options\n"
|
|
76
|
+
"\n"
|
|
77
|
+
" The [`optional`](#optional) decoder is used to decode values that may or may not\n"
|
|
78
|
+
" be present. In other environments these might be called \"nullable\" values.\n"
|
|
79
|
+
"\n"
|
|
80
|
+
" Like the `list` decoder, the `optional` decoder takes another decoder,\n"
|
|
81
|
+
" which is used to decode the value if it is present.\n"
|
|
82
|
+
"\n"
|
|
83
|
+
" ```gleam\n"
|
|
84
|
+
" // Data:\n"
|
|
85
|
+
" // 12.45\n"
|
|
86
|
+
"\n"
|
|
87
|
+
" let result = decode.run(data, decode.optional(decode.float))\n"
|
|
88
|
+
" assert result == Ok(option.Some(12.45))\n"
|
|
89
|
+
" ```\n"
|
|
90
|
+
" ```gleam\n"
|
|
91
|
+
" // Data:\n"
|
|
92
|
+
" // null\n"
|
|
93
|
+
"\n"
|
|
94
|
+
" let result = decode.run(data, decode.optional(decode.int))\n"
|
|
95
|
+
" assert result == Ok(option.None)\n"
|
|
96
|
+
" ```\n"
|
|
97
|
+
"\n"
|
|
98
|
+
" This decoder knows how to handle multiple different runtime representations of\n"
|
|
99
|
+
" absent values, including `Nil`, `None`, `null`, and `undefined`.\n"
|
|
100
|
+
"\n"
|
|
101
|
+
" ## Dicts\n"
|
|
102
|
+
"\n"
|
|
103
|
+
" The [`dict`](#dict) decoder decodes `Dicts` and contains two other decoders, one\n"
|
|
104
|
+
" for the keys, one for the values.\n"
|
|
105
|
+
"\n"
|
|
106
|
+
" ```gleam\n"
|
|
107
|
+
" // Data:\n"
|
|
108
|
+
" // { \"Lucy\" -> 10, \"Nubi\" -> 20 }\n"
|
|
109
|
+
"\n"
|
|
110
|
+
" let result = decode.run(data, decode.dict(decode.string, decode.int))\n"
|
|
111
|
+
" assert result == Ok(dict.from_list([\n"
|
|
112
|
+
" #(\"Lucy\", 10),\n"
|
|
113
|
+
" #(\"Nubi\", 20),\n"
|
|
114
|
+
" ]))\n"
|
|
115
|
+
" ```\n"
|
|
116
|
+
"\n"
|
|
117
|
+
" ## Indexing objects\n"
|
|
118
|
+
"\n"
|
|
119
|
+
" The [`at`](#at) decoder can be used to decode a value that is nested within\n"
|
|
120
|
+
" key-value containers such as Gleam dicts, Erlang maps, or JavaScript objects.\n"
|
|
121
|
+
"\n"
|
|
122
|
+
" ```gleam\n"
|
|
123
|
+
" // Data:\n"
|
|
124
|
+
" // { \"one\" -> { \"two\" -> 123 } }\n"
|
|
125
|
+
"\n"
|
|
126
|
+
" let result = decode.run(data, decode.at([\"one\", \"two\"], decode.int))\n"
|
|
127
|
+
" assert result == Ok(123)\n"
|
|
128
|
+
" ```\n"
|
|
129
|
+
"\n"
|
|
130
|
+
" ## Indexing arrays\n"
|
|
131
|
+
"\n"
|
|
132
|
+
" If you use ints as keys then the [`at`](#at) decoder can be used to index into\n"
|
|
133
|
+
" array-like containers such as Gleam or Erlang tuples, or JavaScript arrays.\n"
|
|
134
|
+
"\n"
|
|
135
|
+
" ```gleam\n"
|
|
136
|
+
" // Data:\n"
|
|
137
|
+
" // [\"one\", \"two\", \"three\"]\n"
|
|
138
|
+
"\n"
|
|
139
|
+
" let result = decode.run(data, decode.at([1], decode.string))\n"
|
|
140
|
+
" assert result == Ok(\"two\")\n"
|
|
141
|
+
" ```\n"
|
|
142
|
+
"\n"
|
|
143
|
+
" ## Records\n"
|
|
144
|
+
"\n"
|
|
145
|
+
" Decoding records from dynamic data is more complex and requires combining a\n"
|
|
146
|
+
" decoder for each field and a special constructor that builds your records with\n"
|
|
147
|
+
" the decoded field values.\n"
|
|
148
|
+
"\n"
|
|
149
|
+
" ```gleam\n"
|
|
150
|
+
" // Data:\n"
|
|
151
|
+
" // {\n"
|
|
152
|
+
" // \"score\" -> 180,\n"
|
|
153
|
+
" // \"name\" -> \"Mel Smith\",\n"
|
|
154
|
+
" // \"is-admin\" -> false,\n"
|
|
155
|
+
" // \"enrolled\" -> true,\n"
|
|
156
|
+
" // \"colour\" -> \"Red\",\n"
|
|
157
|
+
" // }\n"
|
|
158
|
+
"\n"
|
|
159
|
+
" let decoder = {\n"
|
|
160
|
+
" use name <- decode.field(\"name\", decode.string)\n"
|
|
161
|
+
" use score <- decode.field(\"score\", decode.int)\n"
|
|
162
|
+
" use colour <- decode.field(\"colour\", decode.string)\n"
|
|
163
|
+
" use enrolled <- decode.field(\"enrolled\", decode.bool)\n"
|
|
164
|
+
" decode.success(Player(name:, score:, colour:, enrolled:))\n"
|
|
165
|
+
" }\n"
|
|
166
|
+
"\n"
|
|
167
|
+
" let result = decode.run(data, decoder)\n"
|
|
168
|
+
" assert result == Ok(Player(\"Mel Smith\", 180, \"Red\", True))\n"
|
|
169
|
+
" ```\n"
|
|
170
|
+
"\n"
|
|
171
|
+
" ## Enum variants\n"
|
|
172
|
+
"\n"
|
|
173
|
+
" Imagine you have a custom type where all the variants do not contain any values.\n"
|
|
174
|
+
"\n"
|
|
175
|
+
" ```gleam\n"
|
|
176
|
+
" pub type PocketMonsterType {\n"
|
|
177
|
+
" Fire\n"
|
|
178
|
+
" Water\n"
|
|
179
|
+
" Grass\n"
|
|
180
|
+
" Electric\n"
|
|
181
|
+
" }\n"
|
|
182
|
+
" ```\n"
|
|
183
|
+
"\n"
|
|
184
|
+
" You might choose to encode these variants as strings, `\"fire\"` for `Fire`,\n"
|
|
185
|
+
" `\"water\"` for `Water`, and so on. To decode them you'll need to decode the dynamic\n"
|
|
186
|
+
" data as a string, but then you'll need to decode it further still as not all\n"
|
|
187
|
+
" strings are valid values for the enum. This can be done with the `then`\n"
|
|
188
|
+
" function, which enables running a second decoder after the first one\n"
|
|
189
|
+
" succeeds.\n"
|
|
190
|
+
"\n"
|
|
191
|
+
" ```gleam\n"
|
|
192
|
+
" let decoder = {\n"
|
|
193
|
+
" use decoded_string <- decode.then(decode.string)\n"
|
|
194
|
+
" case decoded_string {\n"
|
|
195
|
+
" // Return succeeding decoders for valid strings\n"
|
|
196
|
+
" \"fire\" -> decode.success(Fire)\n"
|
|
197
|
+
" \"water\" -> decode.success(Water)\n"
|
|
198
|
+
" \"grass\" -> decode.success(Grass)\n"
|
|
199
|
+
" \"electric\" -> decode.success(Electric)\n"
|
|
200
|
+
" // Return a failing decoder for any other strings\n"
|
|
201
|
+
" _ -> decode.failure(Fire, expected: \"PocketMonsterType\")\n"
|
|
202
|
+
" }\n"
|
|
203
|
+
" }\n"
|
|
204
|
+
"\n"
|
|
205
|
+
" let result = decode.run(dynamic.string(\"water\"), decoder)\n"
|
|
206
|
+
" assert result == Ok(Water)\n"
|
|
207
|
+
"\n"
|
|
208
|
+
" let result = decode.run(dynamic.string(\"wobble\"), decoder)\n"
|
|
209
|
+
" assert result == Error([DecodeError(\"PocketMonsterType\", \"String\", [])])\n"
|
|
210
|
+
" ```\n"
|
|
211
|
+
"\n"
|
|
212
|
+
" ## Record variants\n"
|
|
213
|
+
"\n"
|
|
214
|
+
" Decoding type variants that contain other values is done by combining the\n"
|
|
215
|
+
" techniques from the \"enum variants\" and \"records\" examples. Imagine you have\n"
|
|
216
|
+
" this custom type that you want to decode:\n"
|
|
217
|
+
"\n"
|
|
218
|
+
" ```gleam\n"
|
|
219
|
+
" pub type PocketMonsterPerson {\n"
|
|
220
|
+
" Trainer(name: String, badge_count: Int)\n"
|
|
221
|
+
" GymLeader(name: String, speciality: PocketMonsterType)\n"
|
|
222
|
+
" }\n"
|
|
223
|
+
" ```\n"
|
|
224
|
+
" And you would like to be able to decode these from dynamic data like this:\n"
|
|
225
|
+
" ```erlang\n"
|
|
226
|
+
" {\n"
|
|
227
|
+
" \"type\" -> \"trainer\",\n"
|
|
228
|
+
" \"name\" -> \"Ash\",\n"
|
|
229
|
+
" \"badge-count\" -> 1,\n"
|
|
230
|
+
" }\n"
|
|
231
|
+
" ```\n"
|
|
232
|
+
" ```erlang\n"
|
|
233
|
+
" {\n"
|
|
234
|
+
" \"type\" -> \"gym-leader\",\n"
|
|
235
|
+
" \"name\" -> \"Misty\",\n"
|
|
236
|
+
" \"speciality\" -> \"water\",\n"
|
|
237
|
+
" }\n"
|
|
238
|
+
" ```\n"
|
|
239
|
+
"\n"
|
|
240
|
+
" Notice how both documents have a `\"type\"` field, which is used to indicate which\n"
|
|
241
|
+
" variant the data is for.\n"
|
|
242
|
+
"\n"
|
|
243
|
+
" First, define decoders for each of the variants:\n"
|
|
244
|
+
"\n"
|
|
245
|
+
" ```gleam\n"
|
|
246
|
+
" let trainer_decoder = {\n"
|
|
247
|
+
" use name <- decode.field(\"name\", decode.string)\n"
|
|
248
|
+
" use badge_count <- decode.field(\"badge-count\", decode.int)\n"
|
|
249
|
+
" decode.success(Trainer(name, badge_count))\n"
|
|
250
|
+
" }\n"
|
|
251
|
+
"\n"
|
|
252
|
+
" let gym_leader_decoder = {\n"
|
|
253
|
+
" use name <- decode.field(\"name\", decode.string)\n"
|
|
254
|
+
" use speciality <- decode.field(\"speciality\", pocket_monster_type_decoder)\n"
|
|
255
|
+
" decode.success(GymLeader(name, speciality))\n"
|
|
256
|
+
" }\n"
|
|
257
|
+
" ```\n"
|
|
258
|
+
"\n"
|
|
259
|
+
" A third decoder can be used to extract and decode the `\"type\"` field, and the\n"
|
|
260
|
+
" expression can evaluate to whichever decoder is suitable for the document.\n"
|
|
261
|
+
"\n"
|
|
262
|
+
" ```gleam\n"
|
|
263
|
+
" // Data:\n"
|
|
264
|
+
" // {\n"
|
|
265
|
+
" // \"type\" -> \"gym-leader\",\n"
|
|
266
|
+
" // \"name\" -> \"Misty\",\n"
|
|
267
|
+
" // \"speciality\" -> \"water\",\n"
|
|
268
|
+
" // }\n"
|
|
269
|
+
"\n"
|
|
270
|
+
" let decoder = {\n"
|
|
271
|
+
" use tag <- decode.field(\"type\", decode.string)\n"
|
|
272
|
+
" case tag {\n"
|
|
273
|
+
" \"gym-leader\" -> gym_leader_decoder\n"
|
|
274
|
+
" _ -> trainer_decoder\n"
|
|
275
|
+
" }\n"
|
|
276
|
+
" }\n"
|
|
277
|
+
"\n"
|
|
278
|
+
" let result = decode.run(data, decoder)\n"
|
|
279
|
+
" assert result == Ok(GymLeader(\"Misty\", Water))\n"
|
|
280
|
+
" ```\n"
|
|
281
|
+
).
|
|
282
|
+
|
|
283
|
+
-type decode_error() :: {decode_error, binary(), binary(), list(binary())}.
|
|
284
|
+
|
|
285
|
+
-opaque decoder(BVV) :: {decoder,
|
|
286
|
+
fun((gleam@dynamic:dynamic_()) -> {BVV, list(decode_error())})}.
|
|
287
|
+
|
|
288
|
+
-file("src/gleam/dynamic/decode.gleam", 357).
|
|
289
|
+
?DOC(
|
|
290
|
+
" Run a decoder on a `Dynamic` value, decoding the value if it is of the\n"
|
|
291
|
+
" desired type, or returning errors.\n"
|
|
292
|
+
"\n"
|
|
293
|
+
" ## Examples\n"
|
|
294
|
+
"\n"
|
|
295
|
+
" ```gleam\n"
|
|
296
|
+
" let decoder = {\n"
|
|
297
|
+
" use name <- decode.field(\"name\", decode.string)\n"
|
|
298
|
+
" use email <- decode.field(\"email\", decode.string)\n"
|
|
299
|
+
" decode.success(SignUp(name: name, email: email))\n"
|
|
300
|
+
" }\n"
|
|
301
|
+
"\n"
|
|
302
|
+
" decode.run(data, decoder)\n"
|
|
303
|
+
" ```\n"
|
|
304
|
+
).
|
|
305
|
+
-spec run(gleam@dynamic:dynamic_(), decoder(BWD)) -> {ok, BWD} |
|
|
306
|
+
{error, list(decode_error())}.
|
|
307
|
+
run(Data, Decoder) ->
|
|
308
|
+
{Maybe_invalid_data, Errors} = (erlang:element(2, Decoder))(Data),
|
|
309
|
+
case Errors of
|
|
310
|
+
[] ->
|
|
311
|
+
{ok, Maybe_invalid_data};
|
|
312
|
+
|
|
313
|
+
[_ | _] ->
|
|
314
|
+
{error, Errors}
|
|
315
|
+
end.
|
|
316
|
+
|
|
317
|
+
-file("src/gleam/dynamic/decode.gleam", 482).
|
|
318
|
+
?DOC(
|
|
319
|
+
" Finalise a decoder having successfully extracted a value.\n"
|
|
320
|
+
"\n"
|
|
321
|
+
" ## Examples\n"
|
|
322
|
+
"\n"
|
|
323
|
+
" ```gleam\n"
|
|
324
|
+
" let data = dynamic.properties([\n"
|
|
325
|
+
" #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n"
|
|
326
|
+
" #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n"
|
|
327
|
+
" ])\n"
|
|
328
|
+
"\n"
|
|
329
|
+
" let decoder = {\n"
|
|
330
|
+
" use name <- decode.field(\"name\", string)\n"
|
|
331
|
+
" use email <- decode.field(\"email\", string)\n"
|
|
332
|
+
" decode.success(SignUp(name: name, email: email))\n"
|
|
333
|
+
" }\n"
|
|
334
|
+
"\n"
|
|
335
|
+
" let result = decode.run(data, decoder)\n"
|
|
336
|
+
" assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n"
|
|
337
|
+
" ```\n"
|
|
338
|
+
).
|
|
339
|
+
-spec success(BXE) -> decoder(BXE).
|
|
340
|
+
success(Data) ->
|
|
341
|
+
{decoder, fun(_) -> {Data, []} end}.
|
|
342
|
+
|
|
343
|
+
-file("src/gleam/dynamic/decode.gleam", 735).
|
|
344
|
+
-spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(),
|
|
345
|
+
list(decode_error())}.
|
|
346
|
+
decode_dynamic(Data) ->
|
|
347
|
+
{Data, []}.
|
|
348
|
+
|
|
349
|
+
-file("src/gleam/dynamic/decode.gleam", 895).
|
|
350
|
+
?DOC(
|
|
351
|
+
" Apply a transformation function to any value decoded by the decoder.\n"
|
|
352
|
+
"\n"
|
|
353
|
+
" ## Examples\n"
|
|
354
|
+
"\n"
|
|
355
|
+
" ```gleam\n"
|
|
356
|
+
" let decoder = decode.int |> decode.map(int.to_string)\n"
|
|
357
|
+
" let result = decode.run(dynamic.int(1000), decoder)\n"
|
|
358
|
+
" assert result == Ok(\"1000\")\n"
|
|
359
|
+
" ```\n"
|
|
360
|
+
).
|
|
361
|
+
-spec map(decoder(CAB), fun((CAB) -> CAD)) -> decoder(CAD).
|
|
362
|
+
map(Decoder, Transformer) ->
|
|
363
|
+
{decoder,
|
|
364
|
+
fun(D) ->
|
|
365
|
+
{Data, Errors} = (erlang:element(2, Decoder))(D),
|
|
366
|
+
{Transformer(Data), Errors}
|
|
367
|
+
end}.
|
|
368
|
+
|
|
369
|
+
-file("src/gleam/dynamic/decode.gleam", 904).
|
|
370
|
+
?DOC(" Apply a transformation function to any errors returned by the decoder.\n").
|
|
371
|
+
-spec map_errors(
|
|
372
|
+
decoder(CAF),
|
|
373
|
+
fun((list(decode_error())) -> list(decode_error()))
|
|
374
|
+
) -> decoder(CAF).
|
|
375
|
+
map_errors(Decoder, Transformer) ->
|
|
376
|
+
{decoder,
|
|
377
|
+
fun(D) ->
|
|
378
|
+
{Data, Errors} = (erlang:element(2, Decoder))(D),
|
|
379
|
+
{Data, Transformer(Errors)}
|
|
380
|
+
end}.
|
|
381
|
+
|
|
382
|
+
-file("src/gleam/dynamic/decode.gleam", 942).
|
|
383
|
+
?DOC(
|
|
384
|
+
" Create a new decoder based upon the value of a previous decoder.\n"
|
|
385
|
+
"\n"
|
|
386
|
+
" This may be useful to run one previous decoder to use in further decoding.\n"
|
|
387
|
+
).
|
|
388
|
+
-spec then(decoder(CAN), fun((CAN) -> decoder(CAP))) -> decoder(CAP).
|
|
389
|
+
then(Decoder, Next) ->
|
|
390
|
+
{decoder,
|
|
391
|
+
fun(Dynamic_data) ->
|
|
392
|
+
{Data, Errors} = (erlang:element(2, Decoder))(Dynamic_data),
|
|
393
|
+
Decoder@1 = Next(Data),
|
|
394
|
+
{Data@1, _} = Layer = (erlang:element(2, Decoder@1))(Dynamic_data),
|
|
395
|
+
case Errors of
|
|
396
|
+
[] ->
|
|
397
|
+
Layer;
|
|
398
|
+
|
|
399
|
+
[_ | _] ->
|
|
400
|
+
{Data@1, Errors}
|
|
401
|
+
end
|
|
402
|
+
end}.
|
|
403
|
+
|
|
404
|
+
-file("src/gleam/dynamic/decode.gleam", 984).
|
|
405
|
+
-spec run_decoders(
|
|
406
|
+
gleam@dynamic:dynamic_(),
|
|
407
|
+
{CAX, list(decode_error())},
|
|
408
|
+
list(decoder(CAX))
|
|
409
|
+
) -> {CAX, list(decode_error())}.
|
|
410
|
+
run_decoders(Data, Failure, Decoders) ->
|
|
411
|
+
case Decoders of
|
|
412
|
+
[] ->
|
|
413
|
+
Failure;
|
|
414
|
+
|
|
415
|
+
[Decoder | Decoders@1] ->
|
|
416
|
+
{_, Errors} = Layer = (erlang:element(2, Decoder))(Data),
|
|
417
|
+
case Errors of
|
|
418
|
+
[] ->
|
|
419
|
+
Layer;
|
|
420
|
+
|
|
421
|
+
[_ | _] ->
|
|
422
|
+
run_decoders(Data, Failure, Decoders@1)
|
|
423
|
+
end
|
|
424
|
+
end.
|
|
425
|
+
|
|
426
|
+
-file("src/gleam/dynamic/decode.gleam", 971).
|
|
427
|
+
?DOC(
|
|
428
|
+
" Create a new decoder from several other decoders. Each of the inner\n"
|
|
429
|
+
" decoders is run in turn, and the value from the first to succeed is used.\n"
|
|
430
|
+
"\n"
|
|
431
|
+
" If no decoder succeeds then the errors from the first decoder are used.\n"
|
|
432
|
+
" If you wish for different errors then you may wish to use the\n"
|
|
433
|
+
" `collapse_errors` or `map_errors` functions.\n"
|
|
434
|
+
"\n"
|
|
435
|
+
" ## Examples\n"
|
|
436
|
+
"\n"
|
|
437
|
+
" ```gleam\n"
|
|
438
|
+
" let decoder = decode.one_of(decode.string, or: [\n"
|
|
439
|
+
" decode.int |> decode.map(int.to_string),\n"
|
|
440
|
+
" decode.float |> decode.map(float.to_string),\n"
|
|
441
|
+
" ])\n"
|
|
442
|
+
" assert decode.run(dynamic.int(1000), decoder) == Ok(\"1000\")\n"
|
|
443
|
+
" ```\n"
|
|
444
|
+
).
|
|
445
|
+
-spec one_of(decoder(CAS), list(decoder(CAS))) -> decoder(CAS).
|
|
446
|
+
one_of(First, Alternatives) ->
|
|
447
|
+
{decoder,
|
|
448
|
+
fun(Dynamic_data) ->
|
|
449
|
+
{_, Errors} = Layer = (erlang:element(2, First))(Dynamic_data),
|
|
450
|
+
case Errors of
|
|
451
|
+
[] ->
|
|
452
|
+
Layer;
|
|
453
|
+
|
|
454
|
+
[_ | _] ->
|
|
455
|
+
run_decoders(Dynamic_data, Layer, Alternatives)
|
|
456
|
+
end
|
|
457
|
+
end}.
|
|
458
|
+
|
|
459
|
+
-file("src/gleam/dynamic/decode.gleam", 1095).
|
|
460
|
+
?DOC(
|
|
461
|
+
" Create a decoder that can refer to itself, useful for decoding deeply\n"
|
|
462
|
+
" nested data.\n"
|
|
463
|
+
"\n"
|
|
464
|
+
" Attempting to create a recursive decoder without this function could result\n"
|
|
465
|
+
" in an infinite loop. If you are using `field` or other `use`able functions\n"
|
|
466
|
+
" then you may not need to use this function.\n"
|
|
467
|
+
"\n"
|
|
468
|
+
" ## Examples\n"
|
|
469
|
+
"\n"
|
|
470
|
+
" ```gleam\n"
|
|
471
|
+
" type Nested {\n"
|
|
472
|
+
" Nested(List(Nested))\n"
|
|
473
|
+
" Value(String)\n"
|
|
474
|
+
" }\n"
|
|
475
|
+
"\n"
|
|
476
|
+
" fn nested_decoder() -> decode.Decoder(Nested) {\n"
|
|
477
|
+
" use <- decode.recursive\n"
|
|
478
|
+
" decode.one_of(decode.string |> decode.map(Value), [\n"
|
|
479
|
+
" decode.list(nested_decoder()) |> decode.map(Nested),\n"
|
|
480
|
+
" ])\n"
|
|
481
|
+
" }\n"
|
|
482
|
+
" ```\n"
|
|
483
|
+
).
|
|
484
|
+
-spec recursive(fun(() -> decoder(CBI))) -> decoder(CBI).
|
|
485
|
+
recursive(Inner) ->
|
|
486
|
+
{decoder,
|
|
487
|
+
fun(Data) ->
|
|
488
|
+
Decoder = Inner(),
|
|
489
|
+
(erlang:element(2, Decoder))(Data)
|
|
490
|
+
end}.
|
|
491
|
+
|
|
492
|
+
-file("src/gleam/dynamic/decode.gleam", 873).
|
|
493
|
+
?DOC(
|
|
494
|
+
" A decoder that decodes nullable values of a type decoded by with a given\n"
|
|
495
|
+
" decoder.\n"
|
|
496
|
+
"\n"
|
|
497
|
+
" This function can handle common representations of null on all runtimes, such as\n"
|
|
498
|
+
" `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on\n"
|
|
499
|
+
" JavaScript.\n"
|
|
500
|
+
"\n"
|
|
501
|
+
" ## Examples\n"
|
|
502
|
+
"\n"
|
|
503
|
+
" ```gleam\n"
|
|
504
|
+
" let result = decode.run(dynamic.int(100), decode.optional(decode.int))\n"
|
|
505
|
+
" assert result == Ok(option.Some(100))\n"
|
|
506
|
+
" ```\n"
|
|
507
|
+
"\n"
|
|
508
|
+
" ```gleam\n"
|
|
509
|
+
" let result = decode.run(dynamic.nil(), decode.optional(decode.int))\n"
|
|
510
|
+
" assert result == Ok(option.None)\n"
|
|
511
|
+
" ```\n"
|
|
512
|
+
).
|
|
513
|
+
-spec optional(decoder(BZX)) -> decoder(gleam@option:option(BZX)).
|
|
514
|
+
optional(Inner) ->
|
|
515
|
+
{decoder, fun(Data) -> case gleam_stdlib:is_null(Data) of
|
|
516
|
+
true ->
|
|
517
|
+
{none, []};
|
|
518
|
+
|
|
519
|
+
false ->
|
|
520
|
+
{Data@1, Errors} = (erlang:element(2, Inner))(Data),
|
|
521
|
+
{{some, Data@1}, Errors}
|
|
522
|
+
end end}.
|
|
523
|
+
|
|
524
|
+
-file("src/gleam/dynamic/decode.gleam", 488).
|
|
525
|
+
?DOC(" Construct a decode error for some unexpected dynamic data.\n").
|
|
526
|
+
-spec decode_error(binary(), gleam@dynamic:dynamic_()) -> list(decode_error()).
|
|
527
|
+
decode_error(Expected, Found) ->
|
|
528
|
+
[{decode_error, Expected, gleam_stdlib:classify_dynamic(Found), []}].
|
|
529
|
+
|
|
530
|
+
-file("src/gleam/dynamic/decode.gleam", 610).
|
|
531
|
+
-spec run_dynamic_function(
|
|
532
|
+
gleam@dynamic:dynamic_(),
|
|
533
|
+
binary(),
|
|
534
|
+
fun((gleam@dynamic:dynamic_()) -> {ok, BXY} | {error, BXY})
|
|
535
|
+
) -> {BXY, list(decode_error())}.
|
|
536
|
+
run_dynamic_function(Data, Name, F) ->
|
|
537
|
+
case F(Data) of
|
|
538
|
+
{ok, Data@1} ->
|
|
539
|
+
{Data@1, []};
|
|
540
|
+
|
|
541
|
+
{error, Placeholder} ->
|
|
542
|
+
{Placeholder,
|
|
543
|
+
[{decode_error, Name, gleam_stdlib:classify_dynamic(Data), []}]}
|
|
544
|
+
end.
|
|
545
|
+
|
|
546
|
+
-file("src/gleam/dynamic/decode.gleam", 661).
|
|
547
|
+
-spec decode_bool(gleam@dynamic:dynamic_()) -> {boolean(), list(decode_error())}.
|
|
548
|
+
decode_bool(Data) ->
|
|
549
|
+
case gleam_stdlib:identity(true) =:= Data of
|
|
550
|
+
true ->
|
|
551
|
+
{true, []};
|
|
552
|
+
|
|
553
|
+
false ->
|
|
554
|
+
case gleam_stdlib:identity(false) =:= Data of
|
|
555
|
+
true ->
|
|
556
|
+
{false, []};
|
|
557
|
+
|
|
558
|
+
false ->
|
|
559
|
+
{false, decode_error(<<"Bool"/utf8>>, Data)}
|
|
560
|
+
end
|
|
561
|
+
end.
|
|
562
|
+
|
|
563
|
+
-file("src/gleam/dynamic/decode.gleam", 690).
|
|
564
|
+
-spec decode_int(gleam@dynamic:dynamic_()) -> {integer(), list(decode_error())}.
|
|
565
|
+
decode_int(Data) ->
|
|
566
|
+
run_dynamic_function(Data, <<"Int"/utf8>>, fun gleam_stdlib:int/1).
|
|
567
|
+
|
|
568
|
+
-file("src/gleam/dynamic/decode.gleam", 716).
|
|
569
|
+
-spec decode_float(gleam@dynamic:dynamic_()) -> {float(), list(decode_error())}.
|
|
570
|
+
decode_float(Data) ->
|
|
571
|
+
run_dynamic_function(Data, <<"Float"/utf8>>, fun gleam_stdlib:float/1).
|
|
572
|
+
|
|
573
|
+
-file("src/gleam/dynamic/decode.gleam", 750).
|
|
574
|
+
-spec decode_bit_array(gleam@dynamic:dynamic_()) -> {bitstring(),
|
|
575
|
+
list(decode_error())}.
|
|
576
|
+
decode_bit_array(Data) ->
|
|
577
|
+
run_dynamic_function(
|
|
578
|
+
Data,
|
|
579
|
+
<<"BitArray"/utf8>>,
|
|
580
|
+
fun gleam_stdlib:bit_array/1
|
|
581
|
+
).
|
|
582
|
+
|
|
583
|
+
-file("src/gleam/dynamic/decode.gleam", 928).
|
|
584
|
+
?DOC(
|
|
585
|
+
" Replace all errors produced by a decoder with one single error for a named\n"
|
|
586
|
+
" expected type.\n"
|
|
587
|
+
"\n"
|
|
588
|
+
" This function may be useful if you wish to simplify errors before\n"
|
|
589
|
+
" presenting them to a user, particularly when using the `one_of` function.\n"
|
|
590
|
+
"\n"
|
|
591
|
+
" ## Examples\n"
|
|
592
|
+
"\n"
|
|
593
|
+
" ```gleam\n"
|
|
594
|
+
" let decoder = decode.string |> decode.collapse_errors(\"MyThing\")\n"
|
|
595
|
+
" let result = decode.run(dynamic.int(1000), decoder)\n"
|
|
596
|
+
" assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n"
|
|
597
|
+
" ```\n"
|
|
598
|
+
).
|
|
599
|
+
-spec collapse_errors(decoder(CAK), binary()) -> decoder(CAK).
|
|
600
|
+
collapse_errors(Decoder, Name) ->
|
|
601
|
+
{decoder,
|
|
602
|
+
fun(Dynamic_data) ->
|
|
603
|
+
{Data, Errors} = Layer = (erlang:element(2, Decoder))(Dynamic_data),
|
|
604
|
+
case Errors of
|
|
605
|
+
[] ->
|
|
606
|
+
Layer;
|
|
607
|
+
|
|
608
|
+
[_ | _] ->
|
|
609
|
+
{Data, decode_error(Name, Dynamic_data)}
|
|
610
|
+
end
|
|
611
|
+
end}.
|
|
612
|
+
|
|
613
|
+
-file("src/gleam/dynamic/decode.gleam", 1017).
|
|
614
|
+
?DOC(
|
|
615
|
+
" Define a decoder that always fails.\n"
|
|
616
|
+
"\n"
|
|
617
|
+
" The first parameter is a \"placeholder\" value, which is some default value that the\n"
|
|
618
|
+
" decoder uses internally in place of the value that would have been produced\n"
|
|
619
|
+
" if the decoder was successful. It doesn't matter what this value is, it is\n"
|
|
620
|
+
" never returned by the decoder or shown to the user, so pick some arbitrary\n"
|
|
621
|
+
" value. If it is an int you might pick `0`, if it is a list you might pick\n"
|
|
622
|
+
" `[]`.\n"
|
|
623
|
+
"\n"
|
|
624
|
+
" The second parameter is the name of the type that has failed to decode.\n"
|
|
625
|
+
"\n"
|
|
626
|
+
" ```gleam\n"
|
|
627
|
+
" decode.failure(User(name: \"\", score: 0, tags: []), expected: \"User\")\n"
|
|
628
|
+
" ```\n"
|
|
629
|
+
).
|
|
630
|
+
-spec failure(CBC, binary()) -> decoder(CBC).
|
|
631
|
+
failure(Placeholder, Name) ->
|
|
632
|
+
{decoder, fun(D) -> {Placeholder, decode_error(Name, D)} end}.
|
|
633
|
+
|
|
634
|
+
-file("src/gleam/dynamic/decode.gleam", 1058).
|
|
635
|
+
?DOC(
|
|
636
|
+
" Create a decoder for a new data type from a decoding function.\n"
|
|
637
|
+
"\n"
|
|
638
|
+
" This function is used for new primitive types. For example, you might\n"
|
|
639
|
+
" define a decoder for Erlang's pid type.\n"
|
|
640
|
+
"\n"
|
|
641
|
+
" A default \"placeholder\" value is also required to make a decoder. When this\n"
|
|
642
|
+
" decoder is used as part of a larger decoder this placeholder value is used\n"
|
|
643
|
+
" so that the rest of the decoder can continue to run and\n"
|
|
644
|
+
" collect all decoding errors. It doesn't matter what this value is, it is\n"
|
|
645
|
+
" never returned by the decoder or shown to the user, so pick some arbitrary\n"
|
|
646
|
+
" value. If it is an int you might pick `0`, if it is a list you might pick\n"
|
|
647
|
+
" `[]`.\n"
|
|
648
|
+
"\n"
|
|
649
|
+
" If you were to make a decoder for the `Int` type (rather than using the\n"
|
|
650
|
+
" build-in `Int` decoder) you would define it like so:\n"
|
|
651
|
+
"\n"
|
|
652
|
+
" ```gleam\n"
|
|
653
|
+
" pub fn int_decoder() -> decode.Decoder(Int) {\n"
|
|
654
|
+
" let default = \"\"\n"
|
|
655
|
+
" decode.new_primitive_decoder(\"Int\", int_from_dynamic)\n"
|
|
656
|
+
" }\n"
|
|
657
|
+
"\n"
|
|
658
|
+
" @external(erlang, \"my_module\", \"int_from_dynamic\")\n"
|
|
659
|
+
" fn int_from_dynamic(data: Int) -> Result(Int, Int)\n"
|
|
660
|
+
" ```\n"
|
|
661
|
+
"\n"
|
|
662
|
+
" ```erlang\n"
|
|
663
|
+
" -module(my_module).\n"
|
|
664
|
+
" -export([int_from_dynamic/1]).\n"
|
|
665
|
+
"\n"
|
|
666
|
+
" int_from_dynamic(Data) ->\n"
|
|
667
|
+
" case is_integer(Data) of\n"
|
|
668
|
+
" true -> {ok, Data};\n"
|
|
669
|
+
" false -> {error, 0}\n"
|
|
670
|
+
" end.\n"
|
|
671
|
+
" ```\n"
|
|
672
|
+
).
|
|
673
|
+
-spec new_primitive_decoder(
|
|
674
|
+
binary(),
|
|
675
|
+
fun((gleam@dynamic:dynamic_()) -> {ok, CBE} | {error, CBE})
|
|
676
|
+
) -> decoder(CBE).
|
|
677
|
+
new_primitive_decoder(Name, Decoding_function) ->
|
|
678
|
+
{decoder, fun(D) -> case Decoding_function(D) of
|
|
679
|
+
{ok, T} ->
|
|
680
|
+
{T, []};
|
|
681
|
+
|
|
682
|
+
{error, Placeholder} ->
|
|
683
|
+
{Placeholder,
|
|
684
|
+
[{decode_error,
|
|
685
|
+
Name,
|
|
686
|
+
gleam_stdlib:classify_dynamic(D),
|
|
687
|
+
[]}]}
|
|
688
|
+
end end}.
|
|
689
|
+
|
|
690
|
+
-file("src/gleam/dynamic/decode.gleam", 639).
|
|
691
|
+
-spec dynamic_string(gleam@dynamic:dynamic_()) -> {ok, binary()} |
|
|
692
|
+
{error, binary()}.
|
|
693
|
+
dynamic_string(Data) ->
|
|
694
|
+
case gleam_stdlib:bit_array(Data) of
|
|
695
|
+
{ok, Data@1} ->
|
|
696
|
+
case gleam@bit_array:to_string(Data@1) of
|
|
697
|
+
{ok, String} ->
|
|
698
|
+
{ok, String};
|
|
699
|
+
|
|
700
|
+
{error, _} ->
|
|
701
|
+
{error, <<""/utf8>>}
|
|
702
|
+
end;
|
|
703
|
+
|
|
704
|
+
{error, _} ->
|
|
705
|
+
{error, <<""/utf8>>}
|
|
706
|
+
end.
|
|
707
|
+
|
|
708
|
+
-file("src/gleam/dynamic/decode.gleam", 634).
|
|
709
|
+
-spec decode_string(gleam@dynamic:dynamic_()) -> {binary(),
|
|
710
|
+
list(decode_error())}.
|
|
711
|
+
decode_string(Data) ->
|
|
712
|
+
run_dynamic_function(Data, <<"String"/utf8>>, fun dynamic_string/1).
|
|
713
|
+
|
|
714
|
+
-file("src/gleam/dynamic/decode.gleam", 450).
|
|
715
|
+
-spec path_segment_to_string(gleam@dynamic:dynamic_()) -> binary().
|
|
716
|
+
path_segment_to_string(Key) ->
|
|
717
|
+
Decoder = one_of(
|
|
718
|
+
{decoder, fun decode_string/1},
|
|
719
|
+
[begin
|
|
720
|
+
_pipe = {decoder, fun decode_int/1},
|
|
721
|
+
map(_pipe, fun erlang:integer_to_binary/1)
|
|
722
|
+
end,
|
|
723
|
+
begin
|
|
724
|
+
_pipe@1 = {decoder, fun decode_float/1},
|
|
725
|
+
map(_pipe@1, fun gleam_stdlib:float_to_string/1)
|
|
726
|
+
end]
|
|
727
|
+
),
|
|
728
|
+
case run(Key, Decoder) of
|
|
729
|
+
{ok, Key@1} ->
|
|
730
|
+
Key@1;
|
|
731
|
+
|
|
732
|
+
{error, _} ->
|
|
733
|
+
<<<<"<"/utf8, (gleam_stdlib:classify_dynamic(Key))/binary>>/binary,
|
|
734
|
+
">"/utf8>>
|
|
735
|
+
end.
|
|
736
|
+
|
|
737
|
+
-file("src/gleam/dynamic/decode.gleam", 824).
|
|
738
|
+
-spec fold_dict(
|
|
739
|
+
{gleam@dict:dict(BZJ, BZK), list(decode_error())},
|
|
740
|
+
gleam@dynamic:dynamic_(),
|
|
741
|
+
gleam@dynamic:dynamic_(),
|
|
742
|
+
fun((gleam@dynamic:dynamic_()) -> {BZJ, list(decode_error())}),
|
|
743
|
+
fun((gleam@dynamic:dynamic_()) -> {BZK, list(decode_error())})
|
|
744
|
+
) -> {gleam@dict:dict(BZJ, BZK), list(decode_error())}.
|
|
745
|
+
fold_dict(Acc, Key, Value, Key_decoder, Value_decoder) ->
|
|
746
|
+
case Key_decoder(Key) of
|
|
747
|
+
{Key_decoded, []} ->
|
|
748
|
+
case Value_decoder(Value) of
|
|
749
|
+
{Value@1, []} ->
|
|
750
|
+
Dict = gleam@dict:insert(
|
|
751
|
+
erlang:element(1, Acc),
|
|
752
|
+
Key_decoded,
|
|
753
|
+
Value@1
|
|
754
|
+
),
|
|
755
|
+
{Dict, erlang:element(2, Acc)};
|
|
756
|
+
|
|
757
|
+
{_, Errors} ->
|
|
758
|
+
Key_identifier = path_segment_to_string(Key),
|
|
759
|
+
push_path({maps:new(), Errors}, [Key_identifier])
|
|
760
|
+
end;
|
|
761
|
+
|
|
762
|
+
{_, Errors@1} ->
|
|
763
|
+
push_path({maps:new(), Errors@1}, [<<"keys"/utf8>>])
|
|
764
|
+
end.
|
|
765
|
+
|
|
766
|
+
-file("src/gleam/dynamic/decode.gleam", 804).
|
|
767
|
+
?DOC(
|
|
768
|
+
" A decoder that decodes dicts where all keys and values are decoded with\n"
|
|
769
|
+
" given decoders.\n"
|
|
770
|
+
"\n"
|
|
771
|
+
" ## Examples\n"
|
|
772
|
+
"\n"
|
|
773
|
+
" ```gleam\n"
|
|
774
|
+
" let values = dynamic.properties([\n"
|
|
775
|
+
" #(dynamic.string(\"one\"), dynamic.int(1)),\n"
|
|
776
|
+
" #(dynamic.string(\"two\"), dynamic.int(2)),\n"
|
|
777
|
+
" ])\n"
|
|
778
|
+
"\n"
|
|
779
|
+
" let result =\n"
|
|
780
|
+
" decode.run(values, decode.dict(decode.string, decode.int))\n"
|
|
781
|
+
" assert result == Ok(values)\n"
|
|
782
|
+
" ```\n"
|
|
783
|
+
).
|
|
784
|
+
-spec dict(decoder(BZC), decoder(BZE)) -> decoder(gleam@dict:dict(BZC, BZE)).
|
|
785
|
+
dict(Key, Value) ->
|
|
786
|
+
{decoder, fun(Data) -> case gleam_stdlib:dict(Data) of
|
|
787
|
+
{error, _} ->
|
|
788
|
+
{maps:new(), decode_error(<<"Dict"/utf8>>, Data)};
|
|
789
|
+
|
|
790
|
+
{ok, Dict} ->
|
|
791
|
+
gleam@dict:fold(
|
|
792
|
+
Dict,
|
|
793
|
+
{maps:new(), []},
|
|
794
|
+
fun(A, K, V) -> case erlang:element(2, A) of
|
|
795
|
+
[] ->
|
|
796
|
+
fold_dict(
|
|
797
|
+
A,
|
|
798
|
+
K,
|
|
799
|
+
V,
|
|
800
|
+
erlang:element(2, Key),
|
|
801
|
+
erlang:element(2, Value)
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
[_ | _] ->
|
|
805
|
+
A
|
|
806
|
+
end end
|
|
807
|
+
)
|
|
808
|
+
end end}.
|
|
809
|
+
|
|
810
|
+
-file("src/gleam/dynamic/decode.gleam", 772).
|
|
811
|
+
?DOC(
|
|
812
|
+
" A decoder that decodes lists where all elements are decoded with a given\n"
|
|
813
|
+
" decoder.\n"
|
|
814
|
+
"\n"
|
|
815
|
+
" ## Examples\n"
|
|
816
|
+
"\n"
|
|
817
|
+
" ```gleam\n"
|
|
818
|
+
" let result =\n"
|
|
819
|
+
" [1, 2, 3]\n"
|
|
820
|
+
" |> list.map(dynamic.int)\n"
|
|
821
|
+
" |> dynamic.list\n"
|
|
822
|
+
" |> decode.run(decode.list(of: decode.int))\n"
|
|
823
|
+
" assert result == Ok([1, 2, 3])\n"
|
|
824
|
+
" ```\n"
|
|
825
|
+
).
|
|
826
|
+
-spec list(decoder(BYQ)) -> decoder(list(BYQ)).
|
|
827
|
+
list(Inner) ->
|
|
828
|
+
{decoder,
|
|
829
|
+
fun(Data) ->
|
|
830
|
+
gleam_stdlib:list(
|
|
831
|
+
Data,
|
|
832
|
+
erlang:element(2, Inner),
|
|
833
|
+
fun(P, K) -> push_path(P, [K]) end,
|
|
834
|
+
0,
|
|
835
|
+
[]
|
|
836
|
+
)
|
|
837
|
+
end}.
|
|
838
|
+
|
|
839
|
+
-file("src/gleam/dynamic/decode.gleam", 438).
|
|
840
|
+
-spec push_path({BWZ, list(decode_error())}, list(any())) -> {BWZ,
|
|
841
|
+
list(decode_error())}.
|
|
842
|
+
push_path(Layer, Path) ->
|
|
843
|
+
Path@1 = gleam@list:map(Path, fun(Key) -> _pipe = Key,
|
|
844
|
+
_pipe@1 = gleam_stdlib:identity(_pipe),
|
|
845
|
+
path_segment_to_string(_pipe@1) end),
|
|
846
|
+
Errors = gleam@list:map(
|
|
847
|
+
erlang:element(2, Layer),
|
|
848
|
+
fun(Error) ->
|
|
849
|
+
{decode_error,
|
|
850
|
+
erlang:element(2, Error),
|
|
851
|
+
erlang:element(3, Error),
|
|
852
|
+
lists:append(Path@1, erlang:element(4, Error))}
|
|
853
|
+
end
|
|
854
|
+
),
|
|
855
|
+
{erlang:element(1, Layer), Errors}.
|
|
856
|
+
|
|
857
|
+
-file("src/gleam/dynamic/decode.gleam", 402).
|
|
858
|
+
-spec index(
|
|
859
|
+
list(BWN),
|
|
860
|
+
list(BWN),
|
|
861
|
+
fun((gleam@dynamic:dynamic_()) -> {BWQ, list(decode_error())}),
|
|
862
|
+
gleam@dynamic:dynamic_(),
|
|
863
|
+
fun((gleam@dynamic:dynamic_(), list(BWN)) -> {BWQ, list(decode_error())})
|
|
864
|
+
) -> {BWQ, list(decode_error())}.
|
|
865
|
+
index(Path, Position, Inner, Data, Handle_miss) ->
|
|
866
|
+
case Path of
|
|
867
|
+
[] ->
|
|
868
|
+
_pipe = Data,
|
|
869
|
+
_pipe@1 = Inner(_pipe),
|
|
870
|
+
push_path(_pipe@1, lists:reverse(Position));
|
|
871
|
+
|
|
872
|
+
[Key | Path@1] ->
|
|
873
|
+
case gleam_stdlib:index(Data, Key) of
|
|
874
|
+
{ok, {some, Data@1}} ->
|
|
875
|
+
index(Path@1, [Key | Position], Inner, Data@1, Handle_miss);
|
|
876
|
+
|
|
877
|
+
{ok, none} ->
|
|
878
|
+
Handle_miss(Data, [Key | Position]);
|
|
879
|
+
|
|
880
|
+
{error, Kind} ->
|
|
881
|
+
{Default, _} = Inner(Data),
|
|
882
|
+
_pipe@2 = {Default,
|
|
883
|
+
[{decode_error,
|
|
884
|
+
Kind,
|
|
885
|
+
gleam_stdlib:classify_dynamic(Data),
|
|
886
|
+
[]}]},
|
|
887
|
+
push_path(_pipe@2, lists:reverse(Position))
|
|
888
|
+
end
|
|
889
|
+
end.
|
|
890
|
+
|
|
891
|
+
-file("src/gleam/dynamic/decode.gleam", 325).
|
|
892
|
+
?DOC(
|
|
893
|
+
" The same as [`field`](#field), except taking a path to the value rather\n"
|
|
894
|
+
" than a field name.\n"
|
|
895
|
+
"\n"
|
|
896
|
+
" This function will index into dictionaries with any key type, and if the key is\n"
|
|
897
|
+
" an int then it'll also index into Erlang tuples and JavaScript arrays, and\n"
|
|
898
|
+
" the first eight elements of Gleam lists.\n"
|
|
899
|
+
"\n"
|
|
900
|
+
" ## Examples\n"
|
|
901
|
+
"\n"
|
|
902
|
+
" ```gleam\n"
|
|
903
|
+
" let data = dynamic.properties([\n"
|
|
904
|
+
" #(dynamic.string(\"data\"), dynamic.properties([\n"
|
|
905
|
+
" #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n"
|
|
906
|
+
" #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n"
|
|
907
|
+
" ])\n"
|
|
908
|
+
" ])\n"
|
|
909
|
+
"\n"
|
|
910
|
+
" let decoder = {\n"
|
|
911
|
+
" use name <- decode.subfield([\"data\", \"name\"], decode.string)\n"
|
|
912
|
+
" use email <- decode.subfield([\"data\", \"email\"], decode.string)\n"
|
|
913
|
+
" decode.success(SignUp(name: name, email: email))\n"
|
|
914
|
+
" }\n"
|
|
915
|
+
" let result = decode.run(data, decoder)\n"
|
|
916
|
+
" assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n"
|
|
917
|
+
" ```\n"
|
|
918
|
+
).
|
|
919
|
+
-spec subfield(list(any()), decoder(BVY), fun((BVY) -> decoder(BWA))) -> decoder(BWA).
|
|
920
|
+
subfield(Field_path, Field_decoder, Next) ->
|
|
921
|
+
{decoder,
|
|
922
|
+
fun(Data) ->
|
|
923
|
+
{Out, Errors1} = index(
|
|
924
|
+
Field_path,
|
|
925
|
+
[],
|
|
926
|
+
erlang:element(2, Field_decoder),
|
|
927
|
+
Data,
|
|
928
|
+
fun(Data@1, Position) ->
|
|
929
|
+
{Default, _} = (erlang:element(2, Field_decoder))(Data@1),
|
|
930
|
+
_pipe = {Default,
|
|
931
|
+
[{decode_error,
|
|
932
|
+
<<"Field"/utf8>>,
|
|
933
|
+
<<"Nothing"/utf8>>,
|
|
934
|
+
[]}]},
|
|
935
|
+
push_path(_pipe, lists:reverse(Position))
|
|
936
|
+
end
|
|
937
|
+
),
|
|
938
|
+
{Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data),
|
|
939
|
+
{Out@1, lists:append(Errors1, Errors2)}
|
|
940
|
+
end}.
|
|
941
|
+
|
|
942
|
+
-file("src/gleam/dynamic/decode.gleam", 392).
|
|
943
|
+
?DOC(
|
|
944
|
+
" A decoder that decodes a value that is nested within other values. For\n"
|
|
945
|
+
" example, decoding a value that is within some deeply nested JSON objects.\n"
|
|
946
|
+
"\n"
|
|
947
|
+
" This function will index into dictionaries with any key type, and if the key is\n"
|
|
948
|
+
" an int then it'll also index into Erlang tuples and JavaScript arrays, and\n"
|
|
949
|
+
" the first eight elements of Gleam lists.\n"
|
|
950
|
+
"\n"
|
|
951
|
+
" ## Examples\n"
|
|
952
|
+
"\n"
|
|
953
|
+
" ```gleam\n"
|
|
954
|
+
" let decoder = decode.at([\"one\", \"two\"], decode.int)\n"
|
|
955
|
+
"\n"
|
|
956
|
+
" let data = dynamic.properties([\n"
|
|
957
|
+
" #(dynamic.string(\"one\"), dynamic.properties([\n"
|
|
958
|
+
" #(dynamic.string(\"two\"), dynamic.int(1000)),\n"
|
|
959
|
+
" ]),\n"
|
|
960
|
+
" ])\n"
|
|
961
|
+
"\n"
|
|
962
|
+
" assert decode.run(data, decoder) == Ok(1000)\n"
|
|
963
|
+
" ```\n"
|
|
964
|
+
"\n"
|
|
965
|
+
" ```gleam\n"
|
|
966
|
+
" assert dynamic.nil()\n"
|
|
967
|
+
" |> decode.run(decode.optional(decode.int))\n"
|
|
968
|
+
" == Ok(option.None)\n"
|
|
969
|
+
" ```\n"
|
|
970
|
+
).
|
|
971
|
+
-spec at(list(any()), decoder(BWK)) -> decoder(BWK).
|
|
972
|
+
at(Path, Inner) ->
|
|
973
|
+
{decoder,
|
|
974
|
+
fun(Data) ->
|
|
975
|
+
index(
|
|
976
|
+
Path,
|
|
977
|
+
[],
|
|
978
|
+
erlang:element(2, Inner),
|
|
979
|
+
Data,
|
|
980
|
+
fun(Data@1, Position) ->
|
|
981
|
+
{Default, _} = (erlang:element(2, Inner))(Data@1),
|
|
982
|
+
_pipe = {Default,
|
|
983
|
+
[{decode_error,
|
|
984
|
+
<<"Field"/utf8>>,
|
|
985
|
+
<<"Nothing"/utf8>>,
|
|
986
|
+
[]}]},
|
|
987
|
+
push_path(_pipe, lists:reverse(Position))
|
|
988
|
+
end
|
|
989
|
+
)
|
|
990
|
+
end}.
|
|
991
|
+
|
|
992
|
+
-file("src/gleam/dynamic/decode.gleam", 527).
|
|
993
|
+
?DOC(
|
|
994
|
+
" Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n"
|
|
995
|
+
" of the desired type, or returning errors. An error is returned if there is\n"
|
|
996
|
+
" no field for the specified key.\n"
|
|
997
|
+
"\n"
|
|
998
|
+
" This function will index into dictionaries with any key type, and if the key is\n"
|
|
999
|
+
" an int then it'll also index into Erlang tuples and JavaScript arrays, and\n"
|
|
1000
|
+
" the first eight elements of Gleam lists.\n"
|
|
1001
|
+
"\n"
|
|
1002
|
+
" ## Examples\n"
|
|
1003
|
+
"\n"
|
|
1004
|
+
" ```gleam\n"
|
|
1005
|
+
" let data = dynamic.properties([\n"
|
|
1006
|
+
" #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n"
|
|
1007
|
+
" #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n"
|
|
1008
|
+
" ])\n"
|
|
1009
|
+
"\n"
|
|
1010
|
+
" let decoder = {\n"
|
|
1011
|
+
" use name <- decode.field(\"name\", string)\n"
|
|
1012
|
+
" use email <- decode.field(\"email\", string)\n"
|
|
1013
|
+
" decode.success(SignUp(name: name, email: email))\n"
|
|
1014
|
+
" }\n"
|
|
1015
|
+
"\n"
|
|
1016
|
+
" let result = decode.run(data, decoder)\n"
|
|
1017
|
+
" assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n"
|
|
1018
|
+
" ```\n"
|
|
1019
|
+
"\n"
|
|
1020
|
+
" If you wish to decode a value that is more deeply nested within the dynamic\n"
|
|
1021
|
+
" data, see [`subfield`](#subfield) and [`at`](#at).\n"
|
|
1022
|
+
"\n"
|
|
1023
|
+
" If you wish to return a default in the event that a field is not present,\n"
|
|
1024
|
+
" see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at).\n"
|
|
1025
|
+
).
|
|
1026
|
+
-spec field(any(), decoder(BXI), fun((BXI) -> decoder(BXK))) -> decoder(BXK).
|
|
1027
|
+
field(Field_name, Field_decoder, Next) ->
|
|
1028
|
+
subfield([Field_name], Field_decoder, Next).
|
|
1029
|
+
|
|
1030
|
+
-file("src/gleam/dynamic/decode.gleam", 560).
|
|
1031
|
+
?DOC(
|
|
1032
|
+
" Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n"
|
|
1033
|
+
" of the desired type, or returning errors. The given default value is\n"
|
|
1034
|
+
" returned if there is no field for the specified key.\n"
|
|
1035
|
+
"\n"
|
|
1036
|
+
" This function will index into dictionaries with any key type, and if the key is\n"
|
|
1037
|
+
" an int then it'll also index into Erlang tuples and JavaScript arrays, and\n"
|
|
1038
|
+
" the first eight elements of Gleam lists.\n"
|
|
1039
|
+
"\n"
|
|
1040
|
+
" ## Examples\n"
|
|
1041
|
+
"\n"
|
|
1042
|
+
" ```gleam\n"
|
|
1043
|
+
" let data = dynamic.properties([\n"
|
|
1044
|
+
" #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n"
|
|
1045
|
+
" ])\n"
|
|
1046
|
+
"\n"
|
|
1047
|
+
" let decoder = {\n"
|
|
1048
|
+
" use name <- decode.field(\"name\", string)\n"
|
|
1049
|
+
" use email <- decode.optional_field(\"email\", \"n/a\", string)\n"
|
|
1050
|
+
" decode.success(SignUp(name: name, email: email))\n"
|
|
1051
|
+
" }\n"
|
|
1052
|
+
"\n"
|
|
1053
|
+
" let result = decode.run(data, decoder)\n"
|
|
1054
|
+
" assert result == Ok(SignUp(name: \"Lucy\", email: \"n/a\"))\n"
|
|
1055
|
+
" ```\n"
|
|
1056
|
+
).
|
|
1057
|
+
-spec optional_field(any(), BXO, decoder(BXO), fun((BXO) -> decoder(BXQ))) -> decoder(BXQ).
|
|
1058
|
+
optional_field(Key, Default, Field_decoder, Next) ->
|
|
1059
|
+
{decoder,
|
|
1060
|
+
fun(Data) ->
|
|
1061
|
+
{Out, Errors1} = begin
|
|
1062
|
+
_pipe = case gleam_stdlib:index(Data, Key) of
|
|
1063
|
+
{ok, {some, Data@1}} ->
|
|
1064
|
+
(erlang:element(2, Field_decoder))(Data@1);
|
|
1065
|
+
|
|
1066
|
+
{ok, none} ->
|
|
1067
|
+
{Default, []};
|
|
1068
|
+
|
|
1069
|
+
{error, Kind} ->
|
|
1070
|
+
{Default,
|
|
1071
|
+
[{decode_error,
|
|
1072
|
+
Kind,
|
|
1073
|
+
gleam_stdlib:classify_dynamic(Data),
|
|
1074
|
+
[]}]}
|
|
1075
|
+
end,
|
|
1076
|
+
push_path(_pipe, [Key])
|
|
1077
|
+
end,
|
|
1078
|
+
{Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data),
|
|
1079
|
+
{Out@1, lists:append(Errors1, Errors2)}
|
|
1080
|
+
end}.
|
|
1081
|
+
|
|
1082
|
+
-file("src/gleam/dynamic/decode.gleam", 600).
|
|
1083
|
+
?DOC(
|
|
1084
|
+
" A decoder that decodes a value that is nested within other values. For\n"
|
|
1085
|
+
" example, decoding a value that is within some deeply nested JSON objects.\n"
|
|
1086
|
+
"\n"
|
|
1087
|
+
" This function will index into dictionaries with any key type, and if the key is\n"
|
|
1088
|
+
" an int then it'll also index into Erlang tuples and JavaScript arrays, and\n"
|
|
1089
|
+
" the first eight elements of Gleam lists.\n"
|
|
1090
|
+
"\n"
|
|
1091
|
+
" ## Examples\n"
|
|
1092
|
+
"\n"
|
|
1093
|
+
" ```gleam\n"
|
|
1094
|
+
" let decoder = decode.optionally_at([\"one\", \"two\"], 100, decode.int)\n"
|
|
1095
|
+
"\n"
|
|
1096
|
+
" let data = dynamic.properties([\n"
|
|
1097
|
+
" #(dynamic.string(\"one\"), dynamic.properties([])),\n"
|
|
1098
|
+
" ])\n"
|
|
1099
|
+
"\n"
|
|
1100
|
+
" assert decode.run(data, decoder) == Ok(100)\n"
|
|
1101
|
+
" ```\n"
|
|
1102
|
+
).
|
|
1103
|
+
-spec optionally_at(list(any()), BXV, decoder(BXV)) -> decoder(BXV).
|
|
1104
|
+
optionally_at(Path, Default, Inner) ->
|
|
1105
|
+
{decoder,
|
|
1106
|
+
fun(Data) ->
|
|
1107
|
+
index(
|
|
1108
|
+
Path,
|
|
1109
|
+
[],
|
|
1110
|
+
erlang:element(2, Inner),
|
|
1111
|
+
Data,
|
|
1112
|
+
fun(_, _) -> {Default, []} end
|
|
1113
|
+
)
|
|
1114
|
+
end}.
|