-module(convert). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/convert.gleam"). -export([object/1, success/1, encode/1, decode/1, string/0, bool/0, float/0, int/0, dynamic/0, bit_array/0, null/0, list/1, result/2, field/4, optional/1, dict/2, enum/2, map/4, type_def/1, default_value/1]). -export_type([glitr_type/0, glitr_value/0, converter/1, partial_converter/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type glitr_type() :: string | bool | float | int | dynamic | bit_array | null | {list, glitr_type()} | {dict, glitr_type(), glitr_type()} | {object, list({binary(), glitr_type()})} | {optional, glitr_type()} | {result, glitr_type(), glitr_type()} | {enum, list({binary(), glitr_type()})}. -type glitr_value() :: {string_value, binary()} | {bool_value, boolean()} | {float_value, float()} | {int_value, integer()} | {dynamic_value, gleam@dynamic:dynamic_()} | {bit_array_value, bitstring()} | null_value | {list_value, list(glitr_value())} | {dict_value, gleam@dict:dict(glitr_value(), glitr_value())} | {object_value, list({binary(), glitr_value()})} | {optional_value, gleam@option:option(glitr_value())} | {result_value, {ok, glitr_value()} | {error, glitr_value()}} | {enum_value, binary(), glitr_value()}. -opaque converter(DTS) :: {converter, fun((DTS) -> glitr_value()), fun((glitr_value()) -> {ok, DTS} | {error, list(gleam@dynamic@decode:decode_error())}), glitr_type(), DTS}. -opaque partial_converter(DTT) :: {partial_converter, fun((DTT) -> glitr_value()), fun((glitr_value()) -> {ok, DTT} | {error, list(gleam@dynamic@decode:decode_error())}), list({binary(), glitr_type()}), {ok, DTT} | {error, list(gleam@dynamic@decode:decode_error())}}. -file("src/convert.gleam", 84). ?DOC( " Create a Converter from a PartialConverter\n" " \n" " Example:\n" " ```\n" " type Person {\n" " Person(name: String, age: Int)\n" " }\n" " \n" " let convert = object({\n" " use name <- field(\"name\", fn(v: Person) { Ok(v.name) }, string())\n" " use age <- field(\"age\", fn(v: Person) { Ok(v.age) }, int())\n" " success(Person(name:, age:))\n" " })\n" " ```\n" ). -spec object(partial_converter(DTU)) -> converter(DTU). object(Converter) -> Default_value@1 = case erlang:element(5, Converter) of {ok, Default_value} -> Default_value; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"convert"/utf8>>, function => <<"object"/utf8>>, line => 85, value => _assert_fail, start => 2558, 'end' => 2612, pattern_start => 2569, pattern_end => 2586}) end, {converter, erlang:element(2, Converter), erlang:element(3, Converter), {object, erlang:element(4, Converter)}, Default_value@1}. -file("src/convert.gleam", 157). ?DOC( " Used to initialize a PartialConverter \n" " See `object` for its usage details\n" ). -spec success(DUE) -> partial_converter(DUE). success(C) -> {partial_converter, fun(_) -> {object_value, []} end, fun(_) -> {ok, C} end, [], {ok, C}}. -file("src/convert.gleam", 522). -spec get_type(glitr_value()) -> binary(). get_type(Val) -> case Val of {bool_value, _} -> <<"BoolValue"/utf8>>; {dict_value, _} -> <<"DictValue"/utf8>>; {enum_value, _, _} -> <<"EnumValue"/utf8>>; {float_value, _} -> <<"FloatValue"/utf8>>; {int_value, _} -> <<"IntValue"/utf8>>; {dynamic_value, _} -> <<"DynamicValue"/utf8>>; {bit_array_value, _} -> <<"BitArrayValue"/utf8>>; {list_value, _} -> <<"ListValue"/utf8>>; null_value -> <<"NullValue"/utf8>>; {object_value, _} -> <<"ObjectValue"/utf8>>; {optional_value, _} -> <<"OptionalValue"/utf8>>; {result_value, _} -> <<"ResultValue"/utf8>>; {string_value, _} -> <<"StringValue"/utf8>> end. -file("src/convert.gleam", 542). ?DOC( " Encode a value into the corresponding GlitrValue using the converter. \n" " If the converter isn't valid, a NullValue is returned.\n" ). -spec encode(converter(DVU)) -> fun((DVU) -> glitr_value()). encode(Converter) -> erlang:element(2, Converter). -file("src/convert.gleam", 547). ?DOC(" Decode a GlitrValue using the provided converter.\n"). -spec decode(converter(DVW)) -> fun((glitr_value()) -> {ok, DVW} | {error, list(gleam@dynamic@decode:decode_error())}). decode(Converter) -> erlang:element(3, Converter). -file("src/convert.gleam", 162). ?DOC(" Basic converter for a String value\n"). -spec string() -> converter(binary()). string() -> {converter, fun(V) -> {string_value, V} end, fun(V@1) -> case V@1 of {string_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"StringValue"/utf8>>, get_type(Other), []}]} end end, string, <<""/utf8>>}. -file("src/convert.gleam", 177). ?DOC(" Basic converter for a Bool value\n"). -spec bool() -> converter(boolean()). bool() -> {converter, fun(V) -> {bool_value, V} end, fun(V@1) -> case V@1 of {bool_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"BoolValue"/utf8>>, get_type(Other), []}]} end end, bool, false}. -file("src/convert.gleam", 192). ?DOC(" Basic converter for a Float value\n"). -spec float() -> converter(float()). float() -> {converter, fun(V) -> {float_value, V} end, fun(V@1) -> case V@1 of {float_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"FloatValue"/utf8>>, get_type(Other), []}]} end end, float, +0.0}. -file("src/convert.gleam", 207). ?DOC(" Basic converter for a Int value\n"). -spec int() -> converter(integer()). int() -> {converter, fun(V) -> {int_value, V} end, fun(V@1) -> case V@1 of {int_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"IntValue"/utf8>>, get_type(Other), []}]} end end, int, 0}. -file("src/convert.gleam", 222). ?DOC(" Basic converter for Dynamic values\n"). -spec dynamic() -> converter(gleam@dynamic:dynamic_()). dynamic() -> {converter, fun(V) -> {dynamic_value, V} end, fun(V@1) -> case V@1 of {dynamic_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"DynamicValue"/utf8>>, get_type(Other), []}]} end end, dynamic, gleam@dynamic:nil()}. -file("src/convert.gleam", 238). ?DOC(" Basic converter for BitArray values\n"). -spec bit_array() -> converter(bitstring()). bit_array() -> {converter, fun(V) -> {bit_array_value, V} end, fun(V@1) -> case V@1 of {bit_array_value, Val} -> {ok, Val}; Other -> {error, [{decode_error, <<"BitArrayValue"/utf8>>, get_type(Other), []}]} end end, bit_array, <<>>}. -file("src/convert.gleam", 254). ?DOC(" Basic converter for a Nil value\n"). -spec null() -> converter(nil). null() -> {converter, fun(_) -> null_value end, fun(V) -> case V of null_value -> {ok, nil}; Other -> {error, [{decode_error, <<"NullValue"/utf8>>, get_type(Other), []}]} end end, null, nil}. -file("src/convert.gleam", 271). ?DOC( " Basic converter for a List value. \n" " \n" " `of` is a converter for the type of the elements.\n" ). -spec list(converter(DUN)) -> converter(list(DUN)). list(Of) -> {converter, fun(V) -> {list_value, begin _pipe = V, gleam@list:map(_pipe, erlang:element(2, Of)) end} end, fun(V@1) -> case V@1 of {list_value, Vals} -> _pipe@1 = Vals, gleam@list:fold( _pipe@1, {ok, []}, fun(Result, Val) -> case {Result, (erlang:element(3, Of))(Val)} of {{ok, Res}, {ok, New_res}} -> {ok, lists:append(Res, [New_res])}; {{error, Errs}, {error, New_errs}} -> {error, lists:append(Errs, New_errs)}; {_, {error, Errs@1}} -> {error, Errs@1}; {{error, Errs@1}, _} -> {error, Errs@1} end end ); Other -> {error, [{decode_error, <<"ListValue"/utf8>>, get_type(Other), []}]} end end, {list, erlang:element(4, Of)}, []}. -file("src/convert.gleam", 317). ?DOC( " Basic converter for a Result value.\n" " \n" " `res` is a converter for the Ok value.\n" " `error` is a converter for the Error value.\n" ). -spec result(converter(DUV), converter(DUX)) -> converter({ok, DUV} | {error, DUX}). result(Res, Error) -> {converter, fun(V) -> {result_value, begin _pipe = V, _pipe@1 = gleam@result:map(_pipe, erlang:element(2, Res)), gleam@result:map_error(_pipe@1, erlang:element(2, Error)) end} end, fun(V@1) -> case V@1 of {result_value, {ok, Val}} -> _pipe@2 = Val, _pipe@3 = (erlang:element(3, Res))(_pipe@2), gleam@result:map(_pipe@3, fun(Field@0) -> {ok, Field@0} end); {result_value, {error, Val@1}} -> _pipe@4 = Val@1, _pipe@5 = (erlang:element(3, Error))(_pipe@4), gleam@result:map( _pipe@5, fun(Field@0) -> {error, Field@0} end ); Other -> {error, [{decode_error, <<"ResultValue"/utf8>>, get_type(Other), []}]} end end, {result, erlang:element(4, Res), erlang:element(4, Error)}, {ok, erlang:element(5, Res)}}. -file("src/convert.gleam", 101). ?DOC( " Add a field to a PartialConverter \n" " See `object` for its usage details\n" " \n" " 'field_name' is the field name that will be used in the converted value. It may not be equal to the actual field name. \n" " 'field_getter' is a function that returns the value of the field from the complete object. \n" " 'field_type' is a Converter associated to the type of the field.\n" ). -spec field( binary(), fun((DTX) -> {ok, DTY} | {error, nil}), converter(DTY), fun((DTY) -> partial_converter(DTX)) ) -> partial_converter(DTX). field(Field_name, Field_getter, Field_type, Next) -> {partial_converter, fun(Base) -> Value = Field_getter(Base), case Value of {error, nil} -> null_value; {ok, Field_value} -> Converter = Next(Field_value), case (erlang:element(2, Converter))(Base) of {object_value, Fields} -> {object_value, [{Field_name, (erlang:element(2, Field_type))( Field_value )} | Fields]}; _ -> null_value end end end, fun(V) -> case V of {object_value, Values} -> Field_value@1 = begin _pipe = Values, _pipe@1 = gleam@list:key_find(_pipe, Field_name), _pipe@2 = gleam@result:replace_error( _pipe@1, [{decode_error, <<"Value"/utf8>>, <<"None"/utf8>>, [Field_name]}] ), gleam@result:then( _pipe@2, erlang:element(3, Field_type) ) end, gleam@result:'try'( Field_value@1, fun(A) -> (erlang:element(3, Next(A)))(V) end ); _ -> {error, []} end end, ([{Field_name, erlang:element(4, Field_type)} | erlang:element(4, Next(erlang:element(5, Field_type)))]), (erlang:element(5, Next(erlang:element(5, Field_type))))}. -file("src/convert.gleam", 296). ?DOC( " Basic converter for a Option value.\n" " \n" " `of` is a converter for the optional value.\n" ). -spec optional(converter(DUR)) -> converter(gleam@option:option(DUR)). optional(Of) -> {converter, fun(V) -> {optional_value, begin _pipe = V, gleam@option:map(_pipe, erlang:element(2, Of)) end} end, fun(V@1) -> case V@1 of {optional_value, none} -> {ok, none}; {optional_value, {some, Val}} -> _pipe@1 = Val, _pipe@2 = (erlang:element(3, Of))(_pipe@1), gleam@result:map( _pipe@2, fun(Field@0) -> {some, Field@0} end ); Other -> {error, [{decode_error, <<"OptionalValue"/utf8>>, get_type(Other), []}]} end end, {optional, erlang:element(4, Of)}, none}. -file("src/convert.gleam", 348). ?DOC( " Basic converter for a Dict value.\n" " \n" " `key` is a converter for the keys.\n" " `value` is a converter for the values.\n" " \n" " Example:\n" " ```\n" " let converter: Converter(Dict(String, Int)) = dict(string(), int())\n" " ```\n" ). -spec dict(converter(DVC), converter(DVE)) -> converter(gleam@dict:dict(DVC, DVE)). dict(Key, Value) -> {converter, fun(V) -> {dict_value, begin _pipe = V, _pipe@1 = maps:to_list(_pipe), _pipe@4 = gleam@list:map( _pipe@1, fun(Kv) -> {begin _pipe@2 = erlang:element(1, Kv), (erlang:element(2, Key))(_pipe@2) end, begin _pipe@3 = erlang:element(2, Kv), (erlang:element(2, Value))(_pipe@3) end} end ), maps:from_list(_pipe@4) end} end, fun(V@1) -> case V@1 of {dict_value, D} -> _pipe@5 = D, _pipe@6 = maps:to_list(_pipe@5), _pipe@7 = gleam@list:fold( _pipe@6, {ok, []}, fun(Result, Kv@1) -> case {Result, (erlang:element(3, Key))( erlang:element(1, Kv@1) ), (erlang:element(3, Value))( erlang:element(2, Kv@1) )} of {{ok, Values}, {ok, New_k}, {ok, New_v}} -> {ok, lists:append(Values, [{New_k, New_v}])}; {{error, Errs}, {ok, _}, {ok, _}} -> {error, Errs}; {{ok, _}, {ok, _}, {error, Errs}} -> {error, Errs}; {{ok, _}, {error, Errs}, {ok, _}} -> {error, Errs}; {{ok, _}, {error, Errs_1}, {error, Errs_2}} -> {error, lists:append(Errs_1, Errs_2)}; {{error, Errs_1}, {error, Errs_2}, {ok, _}} -> {error, lists:append(Errs_1, Errs_2)}; {{error, Errs_1}, {ok, _}, {error, Errs_2}} -> {error, lists:append(Errs_1, Errs_2)}; {{error, Errs@1}, {error, Errs_k}, {error, Errs_v}} -> {error, gleam@list:flatten( [Errs@1, Errs_k, Errs_v] )} end end ), gleam@result:map(_pipe@7, fun maps:from_list/1); Other -> {error, [{decode_error, <<"DictValue"/utf8>>, get_type(Other), []}]} end end, {dict, erlang:element(4, Key), erlang:element(4, Value)}, maps:new()}. -file("src/convert.gleam", 436). ?DOC( " Create a converter for an enum type\n" " \n" " `tags` is a function that associate a tag to each variant of the enum\n" " `converters` is a list of converters, each associated with a tag\n" " \n" " Example:\n" " ```\n" " type Action {\n" " Open(id: String)\n" " Close(id: String)\n" " }\n" " \n" " let open_converter = object({\n" " use id <- field(\"id\", fn(v: Action) {\n" " case v {\n" " Open(id) -> Ok(id)\n" " _ -> Error(Nil)\n" " }\n" " }, string())\n" " success(Open(id:))\n" " })\n" " \n" " let close_converter = object({\n" " use id <- field(\"id\", fn(v: Action) {\n" " case v {\n" " Close(id) -> Ok(id)\n" " _ -> Error(Nil)\n" " }\n" " }, string())\n" " success(Close(id:))\n" " })\n" " \n" " let action_converter = enum(\n" " fn(v) {\n" " case v {\n" " Open(_) -> \"Open\"\n" " Close(_) -> \"Close\"\n" " }\n" " },\n" " [\n" " #(\"Open\", open_converter),\n" " #(\"Close\", close_converter),\n" " ]\n" " )\n" " ```\n" ). -spec enum(fun((DVJ) -> binary()), list({binary(), converter(DVJ)})) -> converter(DVJ). enum(Tags, Converters) -> {converter, fun(V) -> Tag = Tags(V), case begin _pipe = Converters, gleam@list:key_find(_pipe, Tag) end of {ok, Variant} -> {enum_value, Tag, (erlang:element(2, Variant))(V)}; {error, _} -> null_value end end, fun(V@1) -> case V@1 of {enum_value, Variant_name, Value} -> gleam@result:'try'( begin _pipe@1 = Converters, _pipe@2 = gleam@list:key_find(_pipe@1, Variant_name), gleam@result:replace_error( _pipe@2, [{decode_error, <<"One of: "/utf8, (begin _pipe@3 = Converters, _pipe@4 = gleam@list:map( _pipe@3, fun(V@2) -> erlang:element(1, V@2) end ), gleam@string:join( _pipe@4, <<"/"/utf8>> ) end)/binary>>, Variant_name, [<<"0"/utf8>>]}] ) end, fun(Variant@1) -> (erlang:element(3, Variant@1))(Value) end ); Other -> {error, [{decode_error, <<"EnumValue"/utf8>>, get_type(Other), []}]} end end, {enum, begin _pipe@5 = Converters, gleam@list:map( _pipe@5, fun(Var) -> {erlang:element(1, Var), erlang:element(4, (erlang:element(2, Var)))} end ) end}, begin First@1 = case Converters of [First | _] -> First; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"convert"/utf8>>, function => <<"enum"/utf8>>, line => 471, value => _assert_fail, start => 12558, 'end' => 12593, pattern_start => 12569, pattern_end => 12580}) end, erlang:element(5, (erlang:element(2, First@1))) end}. -file("src/convert.gleam", 501). ?DOC( " Create a converter by mapping the encode and decode functions from an existing one\n" " \n" " Example:\n" " ```\n" " pub type Date {\n" " Date(year: Int, month: Int, day: Int)\n" " }\n" " \n" " // We are storing the date as a string for optimized memory storage\n" " pub fn date_converter() -> Converter(Date) {\n" " string()\n" " |> map(\n" " fn(v: Date) { [v.year, v.month, v.day] |> list.map(int.to_string) |> string.join(\"/\") },\n" " fn(v: String) { \n" " let elems = string.split(v, \"/\")\n" " case elems {\n" " [y, m, d, ..] -> Ok(Date(y, m, d))\n" " _ -> Error([])\n" " },\n" " Date(0, 0, 0) // This is required for now...\n" " }\n" " )\n" " }\n" " ```\n" ). -spec map( converter(DVN), fun((DVP) -> DVN), fun((DVN) -> {ok, DVP} | {error, list(gleam@dynamic@decode:decode_error())}), DVP ) -> converter(DVP). map(Converter, Encode_map, Decode_map, Default_value) -> {converter, fun(V) -> A_value = Encode_map(V), (erlang:element(2, Converter))(A_value) end, fun(V@1) -> _pipe = (erlang:element(3, Converter))(V@1), gleam@result:then(_pipe, Decode_map) end, erlang:element(4, Converter), Default_value}. -file("src/convert.gleam", 554). ?DOC(" Return the GlitrType associated with the converter\n"). -spec type_def(converter(any())) -> glitr_type(). type_def(Converter) -> erlang:element(4, Converter). -file("src/convert.gleam", 570). ?DOC( " Retrieve the default value associated with a converter.\n" " \n" " This value is used as a fallback when decoding fails,\n" " especially when building decoders that must return a value\n" " even in the presence of errors.\n" "\n" " ## Example\n" " ```\n" " let string_conv = string()\n" " let default = default_value(string_conv)\n" " // default == \"\"\n" " ```\n" ). -spec default_value(converter(DWD)) -> DWD. default_value(Conv) -> erlang:element(5, Conv).