-module(decode). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([into/1, parameter/1, from/2, map/2, map_errors/2, then/2, list/1, field/3, dict/2, optional/1, collapse_errors/2, one_of/1, at/2, fail/1]). -export_type([decoder/1]). -opaque decoder(FQU) :: {decoder, fun((gleam@dynamic:dynamic_()) -> {ok, FQU} | {error, list(gleam@dynamic:decode_error())})}. -spec into(FQZ) -> decoder(FQZ). into(Constructor) -> {decoder, fun(_) -> {ok, Constructor} end}. -spec parameter(fun((FRB) -> FRC)) -> fun((FRB) -> FRC). parameter(Body) -> Body. -spec from(decoder(FRJ), gleam@dynamic:dynamic_()) -> {ok, FRJ} | {error, list(gleam@dynamic:decode_error())}. from(Decoder, Data) -> (erlang:element(2, Decoder))(Data). -spec map(decoder(FSN), fun((FSN) -> FSP)) -> decoder(FSP). map(Decoder, Transformer) -> {decoder, fun(D) -> case (erlang:element(2, Decoder))(D) of {ok, A} -> {ok, Transformer(A)}; {error, E} -> {error, E} end end}. -spec map_errors( decoder(FSR), fun((list(gleam@dynamic:decode_error())) -> list(gleam@dynamic:decode_error())) ) -> decoder(FSR). map_errors(Decoder, Transformer) -> {decoder, fun(D) -> case (erlang:element(2, Decoder))(D) of {ok, A} -> {ok, A}; {error, E} -> {error, Transformer(E)} end end}. -spec then(decoder(FSZ), fun((FSZ) -> decoder(FTB))) -> decoder(FTB). then(Decoder, Next) -> {decoder, fun(D) -> case (erlang:element(2, Decoder))(D) of {ok, A} -> _pipe = Next(A), from(_pipe, D); {error, E} -> {error, E} end end}. -spec list(decoder(FRM)) -> decoder(list(FRM)). list(Item) -> {decoder, gleam@dynamic:list(erlang:element(2, Item))}. -spec field(decoder(fun((FRD) -> FRE)), any(), decoder(FRD)) -> decoder(FRE). field(Decoder, Field_name, Field_decoder) -> {decoder, fun(Data) -> Constructor = (erlang:element(2, Decoder))(Data), Data@1 = (gleam@dynamic:field( Field_name, fun(_capture) -> from(Field_decoder, _capture) end ))(Data), case {Constructor, Data@1} of {{ok, Constructor@1}, {ok, Data@2}} -> {ok, Constructor@1(Data@2)}; {{error, E1}, {error, E2}} -> {error, lists:append(E1, E2)}; {_, {error, Errors}} -> {error, Errors}; {{error, Errors}, _} -> {error, Errors} end end}. -spec dict(decoder(FRQ), decoder(FRS)) -> decoder(gleam@dict:dict(FRQ, FRS)). dict(Key, Value) -> {decoder, gleam@dynamic:dict(erlang:element(2, Key), erlang:element(2, Value))}. -spec optional(decoder(FRX)) -> decoder(gleam@option:option(FRX)). optional(Item) -> {decoder, gleam@dynamic:optional(erlang:element(2, Item))}. -spec collapse_errors(decoder(FSW), binary()) -> decoder(FSW). collapse_errors(Decoder, Name) -> {decoder, fun(D) -> case (erlang:element(2, Decoder))(D) of {ok, A} -> {ok, A}; {error, _} -> {error, [{decode_error, Name, gleam@dynamic:classify(D), []}]} end end}. -spec run_decoders(gleam@dynamic:dynamic_(), list(decoder(FTI))) -> {ok, FTI} | {error, list(gleam@dynamic:decode_error())}. run_decoders(Data, Decoders) -> case Decoders of [] -> {error, [{decode_error, <<"nothing"/utf8>>, gleam@dynamic:classify(Data), []}]}; [Decoder] -> from(Decoder, Data); [Decoder@1 | Decoders@1] -> case from(Decoder@1, Data) of {ok, Value} -> {ok, Value}; {error, _} -> run_decoders(Data, Decoders@1) end end. -spec one_of(list(decoder(FTE))) -> decoder(FTE). one_of(Decoders) -> {decoder, fun(D) -> run_decoders(D, Decoders) end}. -spec push_path(list(gleam@dynamic:decode_error()), any()) -> list(gleam@dynamic:decode_error()). push_path(Errors, Key) -> Key@1 = gleam@dynamic:from(Key), Decoder = gleam@dynamic:any( [fun gleam@dynamic:string/1, fun(X) -> gleam@result:map( gleam@dynamic:int(X), fun gleam@int:to_string/1 ) end] ), Key@3 = case Decoder(Key@1) of {ok, Key@2} -> Key@2; {error, _} -> <<<<"<"/utf8, (gleam@dynamic:classify(Key@1))/binary>>/binary, ">"/utf8>> end, gleam@list:map( Errors, fun(Error) -> erlang:setelement(4, Error, [Key@3 | erlang:element(4, Error)]) end ). -spec index( any(), fun((gleam@dynamic:dynamic_()) -> {ok, FSH} | {error, list(gleam@dynamic:decode_error())}), gleam@dynamic:dynamic_() ) -> {ok, FSH} | {error, list(gleam@dynamic:decode_error())}. index(Key, Inner, Data) -> case decode_ffi:index(Data, Key) of {ok, Data@1} -> case Inner(Data@1) of {ok, Data@2} -> {ok, Data@2}; {error, Errors} -> {error, push_path(Errors, Key)} end; {error, Kind} -> {error, [{decode_error, Kind, gleam@dynamic:classify(Data), []}]} end. -spec at(list(any()), decoder(FSD)) -> decoder(FSD). at(Path, Inner) -> {decoder, fun(Data) -> Decoder = gleam@list:fold_right( Path, erlang:element(2, Inner), fun(Dyn_decoder, Segment) -> fun(_capture) -> index(Segment, Dyn_decoder, _capture) end end ), Decoder(Data) end}. -spec fail(binary()) -> decoder(any()). fail(Expected) -> {decoder, fun(D) -> {error, [{decode_error, Expected, gleam@dynamic:classify(D), []}]} end}.