257
257
//// ```
258
258
259
259
import gleam/dict . { type Dict }
260
- import gleam/dynamic . { type DecodeError , DecodeError }
260
+ import gleam/dynamic
261
261
import gleam/int
262
262
import gleam/list
263
263
import gleam/option . { type Option , None , Some }
@@ -271,14 +271,20 @@ import gleam/result
271
271
pub type Dynamic =
272
272
dynamic . Dynamic
273
273
274
+ /// Error returned when unexpected data is encountered
275
+ ///
276
+ pub type DecodeError {
277
+ DecodeError ( expected : String , found : String , path : List ( String ) )
278
+ }
279
+
274
280
/// A decoder is a value that can be used to turn dynamically typed `Dynamic`
275
281
/// data into typed data using the `run` function.
276
282
///
277
283
/// Several smaller decoders can be combined to make larger decoders using
278
284
/// functions such as `list` and `field`.
279
285
///
280
286
pub opaque type Decoder ( t) {
281
- Decoder ( function : fn ( Dynamic ) -> # ( t, List ( dynamic . DecodeError ) ) )
287
+ Decoder ( function : fn ( Dynamic ) -> # ( t, List ( DecodeError ) ) )
282
288
}
283
289
284
290
/// The same as [`field`](#field), except taking a path to the value rather
@@ -339,10 +345,7 @@ pub fn subfield(
339
345
/// decode.run(data, decoder)
340
346
/// ```
341
347
///
342
- pub fn run (
343
- data : Dynamic ,
344
- decoder : Decoder ( t) ,
345
- ) -> Result ( t, List ( dynamic . DecodeError ) ) {
348
+ pub fn run ( data : Dynamic , decoder : Decoder ( t) ) -> Result ( t, List ( DecodeError ) ) {
346
349
let # ( maybe_invalid_data , errors ) = decoder . function ( data )
347
350
case errors {
348
351
[ ] -> Ok ( maybe_invalid_data )
@@ -392,10 +395,10 @@ pub fn at(path: List(segment), inner: Decoder(a)) -> Decoder(a) {
392
395
fn index (
393
396
path : List ( a) ,
394
397
position : List ( a) ,
395
- inner : fn ( Dynamic ) -> # ( b, List ( dynamic . DecodeError ) ) ,
398
+ inner : fn ( Dynamic ) -> # ( b, List ( DecodeError ) ) ,
396
399
data : Dynamic ,
397
- handle_miss : fn ( Dynamic , List ( a) ) -> # ( b, List ( dynamic . DecodeError ) ) ,
398
- ) -> # ( b, List ( dynamic . DecodeError ) ) {
400
+ handle_miss : fn ( Dynamic , List ( a) ) -> # ( b, List ( DecodeError ) ) ,
401
+ ) -> # ( b, List ( DecodeError ) ) {
399
402
case path {
400
403
[ ] -> {
401
404
inner ( data )
@@ -477,7 +480,7 @@ pub fn success(data: t) -> Decoder(t) {
477
480
pub fn decode_error (
478
481
expected expected : String ,
479
482
found found : Dynamic ,
480
- ) -> List ( dynamic . DecodeError ) {
483
+ ) -> List ( DecodeError ) {
481
484
[ DecodeError ( expected : expected , found : dynamic . classify ( found ) , path : [ ] ) ]
482
485
}
483
486
@@ -601,10 +604,14 @@ fn run_dynamic_function(
601
604
data : Dynamic ,
602
605
zero : t,
603
606
f : dynamic . Decoder ( t) ,
604
- ) -> # ( t, List ( dynamic . DecodeError ) ) {
607
+ ) -> # ( t, List ( DecodeError ) ) {
605
608
case f ( data ) {
606
609
Ok ( data ) -> # ( data , [ ] )
607
- Error ( errors ) -> # ( zero , errors )
610
+ Error ( errors ) -> {
611
+ let errors =
612
+ list . map ( errors , fn ( e ) { DecodeError ( e . expected , e . found , e . path ) } )
613
+ # ( zero , errors )
614
+ }
608
615
}
609
616
}
610
617
@@ -619,7 +626,7 @@ fn run_dynamic_function(
619
626
///
620
627
pub const string : Decoder ( String ) = Decoder ( decode_string )
621
628
622
- fn decode_string ( data : Dynamic ) -> # ( String , List ( dynamic . DecodeError ) ) {
629
+ fn decode_string ( data : Dynamic ) -> # ( String , List ( DecodeError ) ) {
623
630
run_dynamic_function ( data , "" , dynamic . string )
624
631
}
625
632
@@ -634,7 +641,7 @@ fn decode_string(data: Dynamic) -> #(String, List(dynamic.DecodeError)) {
634
641
///
635
642
pub const bool : Decoder ( Bool ) = Decoder ( decode_bool )
636
643
637
- fn decode_bool ( data : Dynamic ) -> # ( Bool , List ( dynamic . DecodeError ) ) {
644
+ fn decode_bool ( data : Dynamic ) -> # ( Bool , List ( DecodeError ) ) {
638
645
run_dynamic_function ( data , False , dynamic . bool )
639
646
}
640
647
@@ -649,7 +656,7 @@ fn decode_bool(data: Dynamic) -> #(Bool, List(dynamic.DecodeError)) {
649
656
///
650
657
pub const int : Decoder ( Int ) = Decoder ( decode_int )
651
658
652
- fn decode_int ( data : Dynamic ) -> # ( Int , List ( dynamic . DecodeError ) ) {
659
+ fn decode_int ( data : Dynamic ) -> # ( Int , List ( DecodeError ) ) {
653
660
run_dynamic_function ( data , 0 , dynamic . int )
654
661
}
655
662
@@ -664,7 +671,7 @@ fn decode_int(data: Dynamic) -> #(Int, List(dynamic.DecodeError)) {
664
671
///
665
672
pub const float : Decoder ( Float ) = Decoder ( decode_float )
666
673
667
- fn decode_float ( data : Dynamic ) -> # ( Float , List ( dynamic . DecodeError ) ) {
674
+ fn decode_float ( data : Dynamic ) -> # ( Float , List ( DecodeError ) ) {
668
675
run_dynamic_function ( data , 0.0 , dynamic . float )
669
676
}
670
677
@@ -679,7 +686,7 @@ fn decode_float(data: Dynamic) -> #(Float, List(dynamic.DecodeError)) {
679
686
///
680
687
pub const dynamic : Decoder ( Dynamic ) = Decoder ( decode_dynamic )
681
688
682
- fn decode_dynamic ( data : Dynamic ) -> # ( Dynamic , List ( dynamic . DecodeError ) ) {
689
+ fn decode_dynamic ( data : Dynamic ) -> # ( Dynamic , List ( DecodeError ) ) {
683
690
# ( data , [ ] )
684
691
}
685
692
@@ -694,7 +701,7 @@ fn decode_dynamic(data: Dynamic) -> #(Dynamic, List(dynamic.DecodeError)) {
694
701
///
695
702
pub const bit_array : Decoder ( BitArray ) = Decoder ( decode_bit_array )
696
703
697
- fn decode_bit_array ( data : Dynamic ) -> # ( BitArray , List ( dynamic . DecodeError ) ) {
704
+ fn decode_bit_array ( data : Dynamic ) -> # ( BitArray , List ( DecodeError ) ) {
698
705
run_dynamic_function ( data , << >> , dynamic . bit_array )
699
706
}
700
707
@@ -719,11 +726,11 @@ pub fn list(of inner: Decoder(a)) -> Decoder(List(a)) {
719
726
@ external ( javascript , "../../gleam_stdlib_decode_ffi.mjs" , "list" )
720
727
fn decode_list (
721
728
data : Dynamic ,
722
- item : fn ( Dynamic ) -> # ( t, List ( dynamic . DecodeError ) ) ,
729
+ item : fn ( Dynamic ) -> # ( t, List ( DecodeError ) ) ,
723
730
push_path : fn ( # ( t, List ( DecodeError ) ) , key) -> # ( t, List ( DecodeError ) ) ,
724
731
index : Int ,
725
732
acc : List ( t) ,
726
- ) -> # ( List ( t) , List ( dynamic . DecodeError ) )
733
+ ) -> # ( List ( t) , List ( DecodeError ) )
727
734
728
735
/// A decoder that decodes dicts where all keys and vales are decoded with
729
736
/// given decoders.
@@ -762,12 +769,12 @@ pub fn dict(
762
769
}
763
770
764
771
fn fold_dict (
765
- acc : # ( Dict ( k, v) , List ( dynamic . DecodeError ) ) ,
772
+ acc : # ( Dict ( k, v) , List ( DecodeError ) ) ,
766
773
key : Dynamic ,
767
774
value : Dynamic ,
768
- key_decoder : fn ( Dynamic ) -> # ( k, List ( dynamic . DecodeError ) ) ,
769
- value_decoder : fn ( Dynamic ) -> # ( v, List ( dynamic . DecodeError ) ) ,
770
- ) -> # ( Dict ( k, v) , List ( dynamic . DecodeError ) ) {
775
+ key_decoder : fn ( Dynamic ) -> # ( k, List ( DecodeError ) ) ,
776
+ value_decoder : fn ( Dynamic ) -> # ( v, List ( DecodeError ) ) ,
777
+ ) -> # ( Dict ( k, v) , List ( DecodeError ) ) {
771
778
// First we decode the key.
772
779
case key_decoder ( key ) {
773
780
# ( key , [ ] ) ->
@@ -966,18 +973,24 @@ pub fn failure(zero: a, expected: String) -> Decoder(a) {
966
973
/// import decode/decode
967
974
///
968
975
/// pub fn string_decoder() -> decode.Decoder(String) {
969
- /// decode.new_primitive_decoder(dynamic.string, "")
976
+ /// let default = ""
977
+ /// decode.new_primitive_decoder("String", fn(data) {
978
+ /// case dynamic.string {
979
+ /// Ok(x) -> Ok(x)
980
+ /// Error(x) -> Error(default)
981
+ /// }
982
+ /// })
970
983
/// }
971
984
/// ```
972
985
///
973
986
pub fn new_primitive_decoder (
974
- decoding_function : fn ( Dynamic ) -> Result ( t , List ( DecodeError ) ) ,
975
- zero : t ,
987
+ name : String ,
988
+ decoding_function : fn ( Dynamic ) -> Result ( t , t ) ,
976
989
) -> Decoder ( t) {
977
990
Decoder ( function : fn ( d ) {
978
991
case decoding_function ( d ) {
979
992
Ok ( t ) -> # ( t , [ ] )
980
- Error ( errors ) -> # ( zero , errors )
993
+ Error ( zero ) -> # ( zero , [ DecodeError ( name , dynamic . classify ( d ) , [ ] ) ] )
981
994
}
982
995
} )
983
996
}
0 commit comments