-module(cx). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([dict/0, add_int/3, add_float/3, add_string/3, add_bool/3, get/2, get_list/2, get_strings/2, get_bool/2, get_string/2, add_strings/3, add/3, add_list/3]). -export_type([context/0, context_error/0]). -type context() :: {c_bool, boolean()} | {c_string, binary()} | {c_int, integer()} | {c_float, float()} | {c_dict, gleam@dict:dict(binary(), context())} | {c_list, list(context())}. -type context_error() :: {key_not_found, binary()} | {value_not_found, binary()} | {unexpected_context_type, binary()}. -spec dict() -> context(). dict() -> {c_dict, gleam@dict:new()}. -spec add_int(context(), binary(), integer()) -> context(). add_int(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, {c_int, Value})}; _ -> Context end. -spec add_float(context(), binary(), float()) -> context(). add_float(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, {c_float, Value})}; _ -> Context end. -spec add_string(context(), binary(), binary()) -> context(). add_string(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, {c_string, Value})}; _ -> Context end. -spec add_bool(context(), binary(), boolean()) -> context(). add_bool(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, {c_bool, Value})}; _ -> Context end. -spec get(context(), binary()) -> {ok, context()} | {error, context_error()}. get(Context, Key) -> case Context of {c_dict, D} -> case gleam@dict:get(D, Key) of {ok, V} -> {ok, V}; _ -> {error, {key_not_found, Key}} end; _ -> {error, {unexpected_context_type, Key}} end. -spec get_list_final(context(), binary()) -> {ok, list(context())} | {error, context_error()}. get_list_final(Context, Key) -> case Context of {c_dict, D} -> case gleam@dict:get(D, Key) of {ok, Value} -> case Value of {c_list, L} -> {ok, L}; _ -> {error, {unexpected_context_type, Key}} end; _ -> {error, {key_not_found, Key}} end; _ -> {error, {value_not_found, Key}} end. -spec get_list(context(), binary()) -> {ok, list(context())} | {error, context_error()}. get_list(Context, Key) -> case gleam@string:split(Key, <<"."/utf8>>) of [Key1] -> get_list_final(Context, Key1); [Key1@1, Key2 | _] -> case get(Context, Key1@1) of {ok, Dict1} -> get_list(Dict1, Key2); {error, _} -> {error, {value_not_found, Key1@1}} end; [] -> {error, {value_not_found, Key}} end. -spec get_strings_final(context(), binary()) -> {ok, list(binary())} | {error, context_error()}. get_strings_final(Context, Key) -> case get_list(Context, Key) of {ok, Items} -> {ok, gleam@list:filter_map(Items, fun(Item) -> case Item of {c_string, S} -> {ok, S}; _ -> {error, {unexpected_context_type, Key}} end end)}; {error, _} -> {error, {value_not_found, Key}} end. -spec get_strings(context(), binary()) -> {ok, list(binary())} | {error, context_error()}. get_strings(Context, Key) -> case gleam@string:split(Key, <<"."/utf8>>) of [Key1] -> get_strings_final(Context, Key1); [Key1@1, Key2 | _] -> case get(Context, Key1@1) of {ok, Dict1} -> get_strings(Dict1, Key2); {error, _} -> {error, {value_not_found, Key1@1}} end; [] -> {error, {value_not_found, Key}} end. -spec get_bool_final(context(), binary()) -> {ok, boolean()} | {error, context_error()}. get_bool_final(Context, Key) -> case Context of {c_dict, D} -> case gleam@dict:get(D, Key) of {ok, Value} -> case Value of {c_bool, B} -> {ok, B}; {c_int, I} -> {ok, I /= 0}; {c_float, F} -> {ok, F /= +0.0}; {c_string, S} -> {ok, S /= <<""/utf8>>}; _ -> {error, {unexpected_context_type, Key}} end; _ -> {error, {key_not_found, Key}} end; _ -> {error, {unexpected_context_type, Key}} end. -spec get_bool(context(), binary()) -> {ok, boolean()} | {error, context_error()}. get_bool(Context, Key) -> case gleam@string:split(Key, <<"."/utf8>>) of [Key1] -> get_bool_final(Context, Key1); [Key1@1, Key2 | _] -> case get(Context, Key1@1) of {ok, Dict1} -> get_bool(Dict1, Key2); {error, _} -> {error, {value_not_found, Key1@1}} end; [] -> {error, {value_not_found, Key}} end. -spec get_string_final(context(), binary()) -> {ok, binary()} | {error, context_error()}. get_string_final(Context, Key) -> case Context of {c_dict, D} -> case gleam@dict:get(D, Key) of {ok, Value} -> case Value of {c_int, I} -> {ok, gleam@int:to_string(I)}; {c_string, S} -> {ok, S}; _ -> {error, {unexpected_context_type, Key}} end; _ -> {error, {key_not_found, Key}} end; _ -> {error, {unexpected_context_type, Key}} end. -spec get_string(context(), binary()) -> {ok, binary()} | {error, context_error()}. get_string(Context, Key) -> case gleam@string:split(Key, <<"."/utf8>>) of [Key1] -> get_string_final(Context, Key1); [Key1@1, Key2 | _] -> case get(Context, Key1@1) of {ok, Dict1} -> get_string(Dict1, Key2); {error, _} -> {error, {value_not_found, Key1@1}} end; [] -> {error, {value_not_found, Key}} end. -spec add_strings(context(), binary(), list(binary())) -> context(). add_strings(Context, Key, Values) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert( D, Key, {c_list, gleam@list:map( Values, fun(Value) -> {c_string, Value} end )} )}; _ -> Context end. -spec add(context(), binary(), context()) -> context(). add(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, Value)}; _ -> Context end. -spec add_list(context(), binary(), list(context())) -> context(). add_list(Context, Key, Value) -> case Context of {c_dict, D} -> {c_dict, gleam@dict:insert(D, Key, {c_list, Value})}; _ -> Context end.