Packages
caffeine_lang
4.8.3
6.3.1
6.3.0
6.2.2
6.2.1
6.2.0
6.1.2
6.1.1
6.1.0
6.0.0
5.6.0
5.5.0
5.4.4
5.4.3
5.4.2
5.4.1
5.4.0
5.3.0
5.2.0
5.1.1
5.1.0
5.0.12
5.0.11
5.0.10
5.0.8
5.0.7
5.0.6
5.0.5
5.0.4
5.0.1
5.0.0
4.10.0
4.9.0
4.8.3
4.8.2
4.8.1
4.8.0
4.7.9
4.7.8
4.7.7
4.7.6
4.7.5
4.6.7
4.6.6
4.6.5
4.6.4
4.6.3
4.6.2
4.6.0
4.5.1
4.5.0
4.4.4
4.4.3
4.4.1
4.4.0
4.3.7
4.3.6
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.0.2
1.0.1
0.1.0
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.2
0.0.1
A compiler for generating reliability artifacts from service expectation definitions.
Current section
Files
Jump to
Current section
Files
src/caffeine_lang@types.erl
-module(caffeine_lang@types).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/types.gleam").
-export([numeric_type_meta/1, semantic_type_meta/1, primitive_all_type_metas/0, collection_all_type_metas/0, modifier_all_type_metas/0, completable_type_metas/0, refinement_all_type_metas/0, structured_all_type_metas/0, all_type_metas/0, numeric_type_to_string/1, semantic_type_to_string/1, primitive_type_to_string/1, parse_numeric_type/1, parse_refinement_compatible_primitive/1, parse_semantic_type/1, parse_primitive_type/1, parse_collection_type/2, parse_modifier_type/3, validate_numeric_value/2, validate_numeric_default_value/2, validate_primitive_default_value/2, validate_modifier_default_value_recursive/3, validate_in_range/4, parse_refinement_type/3, resolve_primitive_to_string/3, is_optional_or_defaulted/1, get_numeric_type/1, validate_refinement_default_value/3, parse_accepted_type/1, try_each_inner_parsed/2, try_each_inner/2, map_inner/2, resolve_to_string/4, validate_value/2, parsed_type_to_string/1, collection_type_to_string/1, accepted_type_to_string/1, modifier_type_to_string/1, refinement_type_to_string/1]).
-export_type([accepted_types/0, parsed_type/0, primitive_types/0, numeric_types/0, semantic_string_types/0, collection_types/1, modifier_types/1, refinement_types/1, validation_error/0, type_meta/0]).
-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 accepted_types() :: {primitive_type, primitive_types()} |
{collection_type, collection_types(accepted_types())} |
{modifier_type, modifier_types(accepted_types())} |
{refinement_type, refinement_types(accepted_types())} |
{record_type, gleam@dict:dict(binary(), accepted_types())}.
-type parsed_type() :: {parsed_primitive, primitive_types()} |
{parsed_collection, collection_types(parsed_type())} |
{parsed_modifier, modifier_types(parsed_type())} |
{parsed_refinement, refinement_types(parsed_type())} |
{parsed_type_alias_ref, binary()} |
{parsed_record, gleam@dict:dict(binary(), parsed_type())}.
-type primitive_types() :: boolean |
string |
{numeric_type, numeric_types()} |
{semantic_type, semantic_string_types()}.
-type numeric_types() :: float | integer | percentage.
-type semantic_string_types() :: u_r_l.
-type collection_types(FCR) :: {dict, FCR, FCR} | {list, FCR}.
-type modifier_types(FCS) :: {optional, FCS} | {defaulted, FCS, binary()}.
-type refinement_types(FCT) :: {one_of, FCT, gleam@set:set(binary())} |
{inclusive_range, FCT, binary(), binary()}.
-type validation_error() :: {validation_error,
binary(),
binary(),
list(binary())}.
-type type_meta() :: {type_meta, binary(), binary(), binary(), binary()}.
-file("src/caffeine_lang/types.gleam", 179).
?DOC(false).
-spec numeric_type_meta(numeric_types()) -> type_meta().
numeric_type_meta(Typ) ->
case Typ of
integer ->
{type_meta,
<<"Integer"/utf8>>,
<<"Whole numbers"/utf8>>,
<<"Integer"/utf8>>,
<<"42, 0, -10"/utf8>>};
float ->
{type_meta,
<<"Float"/utf8>>,
<<"Decimal numbers"/utf8>>,
<<"Float"/utf8>>,
<<"3.14, 99.9, 0.0"/utf8>>};
percentage ->
{type_meta,
<<"Percentage"/utf8>>,
<<"A numeric value between 0.0 and 100.0 representing a percentage"/utf8>>,
<<"Percentage"/utf8>>,
<<"99.9%"/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 168).
-spec numeric_all_type_metas() -> list(type_meta()).
numeric_all_type_metas() ->
[numeric_type_meta(integer),
numeric_type_meta(float),
numeric_type_meta(percentage)].
-file("src/caffeine_lang/types.gleam", 212).
?DOC(false).
-spec semantic_type_meta(semantic_string_types()) -> type_meta().
semantic_type_meta(Typ) ->
case Typ of
u_r_l ->
{type_meta,
<<"URL"/utf8>>,
<<"A valid URL starting with http:// or https://"/utf8>>,
<<"URL"/utf8>>,
<<"\"https://example.com\""/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 147).
-spec primitive_type_meta(primitive_types()) -> type_meta().
primitive_type_meta(Typ) ->
case Typ of
boolean ->
{type_meta,
<<"Boolean"/utf8>>,
<<"True or false"/utf8>>,
<<"Boolean"/utf8>>,
<<"true, false"/utf8>>};
string ->
{type_meta,
<<"String"/utf8>>,
<<"Any text between double quotes"/utf8>>,
<<"String"/utf8>>,
<<"\"hello\", \"my-service\""/utf8>>};
{numeric_type, N} ->
numeric_type_meta(N);
{semantic_type, S} ->
semantic_type_meta(S)
end.
-file("src/caffeine_lang/types.gleam", 205).
-spec semantic_all_type_metas() -> list(type_meta()).
semantic_all_type_metas() ->
[semantic_type_meta(u_r_l)].
-file("src/caffeine_lang/types.gleam", 139).
?DOC(false).
-spec primitive_all_type_metas() -> list(type_meta()).
primitive_all_type_metas() ->
lists:append(
[[primitive_type_meta(boolean), primitive_type_meta(string)],
numeric_all_type_metas(),
semantic_all_type_metas()]
).
-file("src/caffeine_lang/types.gleam", 230).
-spec collection_type_meta(collection_types(any())) -> type_meta().
collection_type_meta(Typ) ->
case Typ of
{list, _} ->
{type_meta,
<<"List"/utf8>>,
<<"An ordered sequence where each element shares the same type"/utf8>>,
<<"List(T)"/utf8>>,
<<"List(String), List(Integer)"/utf8>>};
{dict, _, _} ->
{type_meta,
<<"Dict"/utf8>>,
<<"A key-value map with typed keys and values"/utf8>>,
<<"Dict(K, V)"/utf8>>,
<<"Dict(String, String), Dict(String, Integer)"/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 226).
?DOC(false).
-spec collection_all_type_metas() -> list(type_meta()).
collection_all_type_metas() ->
[collection_type_meta({list, nil}), collection_type_meta({dict, nil, nil})].
-file("src/caffeine_lang/types.gleam", 255).
-spec modifier_type_meta(modifier_types(any())) -> type_meta().
modifier_type_meta(Typ) ->
case Typ of
{optional, _} ->
{type_meta,
<<"Optional"/utf8>>,
<<"A type where the value may be left unspecified"/utf8>>,
<<"Optional(T)"/utf8>>,
<<"Optional(String), Optional(Integer)"/utf8>>};
{defaulted, _, _} ->
{type_meta,
<<"Defaulted"/utf8>>,
<<"A type with a default value if none is provided"/utf8>>,
<<"Defaulted(T, default)"/utf8>>,
<<"Defaulted(Integer, 30), Defaulted(String, \"prod\")"/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 251).
?DOC(false).
-spec modifier_all_type_metas() -> list(type_meta()).
modifier_all_type_metas() ->
[modifier_type_meta({optional, nil}),
modifier_type_meta({defaulted, nil, <<""/utf8>>})].
-file("src/caffeine_lang/types.gleam", 129).
?DOC(false).
-spec completable_type_metas() -> list(type_meta()).
completable_type_metas() ->
lists:append(
[primitive_all_type_metas(),
collection_all_type_metas(),
modifier_all_type_metas()]
).
-file("src/caffeine_lang/types.gleam", 283).
-spec refinement_type_meta(refinement_types(any())) -> type_meta().
refinement_type_meta(Typ) ->
case Typ of
{one_of, _, _} ->
{type_meta,
<<"OneOf"/utf8>>,
<<"Value must be one of a finite set"/utf8>>,
<<"T { x | x in { val1, val2, ... } }"/utf8>>,
<<"String { x | x in { datadog, prometheus } }"/utf8>>};
{inclusive_range, _, _, _} ->
{type_meta,
<<"InclusiveRange"/utf8>>,
<<"Value must be within a numeric range (inclusive)"/utf8>>,
<<"T { x | x in ( low..high ) }"/utf8>>,
<<"Integer { x | x in ( 0..100 ) }"/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 276).
?DOC(false).
-spec refinement_all_type_metas() -> list(type_meta()).
refinement_all_type_metas() ->
[refinement_type_meta({one_of, nil, gleam@set:new()}),
refinement_type_meta({inclusive_range, nil, <<""/utf8>>, <<""/utf8>>})].
-file("src/caffeine_lang/types.gleam", 304).
?DOC(false).
-spec structured_all_type_metas() -> list(type_meta()).
structured_all_type_metas() ->
[{type_meta,
<<"Record"/utf8>>,
<<"A group of named, typed fields"/utf8>>,
<<"{ field: T, ... }"/utf8>>,
<<"{ numerator: String, denominator: String }"/utf8>>}].
-file("src/caffeine_lang/types.gleam", 116).
?DOC(false).
-spec all_type_metas() -> list(type_meta()).
all_type_metas() ->
lists:append(
[completable_type_metas(),
structured_all_type_metas(),
refinement_all_type_metas()]
).
-file("src/caffeine_lang/types.gleam", 345).
?DOC(" Converts a NumericTypes to its string representation.\n").
-spec numeric_type_to_string(numeric_types()) -> binary().
numeric_type_to_string(Numeric_type) ->
case Numeric_type of
float ->
<<"Float"/utf8>>;
integer ->
<<"Integer"/utf8>>;
percentage ->
<<"Percentage"/utf8>>
end.
-file("src/caffeine_lang/types.gleam", 354).
?DOC(" Converts a SemanticStringTypes to its string representation.\n").
-spec semantic_type_to_string(semantic_string_types()) -> binary().
semantic_type_to_string(Typ) ->
case Typ of
u_r_l ->
<<"URL"/utf8>>
end.
-file("src/caffeine_lang/types.gleam", 335).
?DOC(false).
-spec primitive_type_to_string(primitive_types()) -> binary().
primitive_type_to_string(Primitive_type) ->
case Primitive_type of
boolean ->
<<"Boolean"/utf8>>;
string ->
<<"String"/utf8>>;
{numeric_type, Numeric_type} ->
numeric_type_to_string(Numeric_type);
{semantic_type, Semantic_type} ->
semantic_type_to_string(Semantic_type)
end.
-file("src/caffeine_lang/types.gleam", 385).
?DOC(" Generic collection-to-string using a recursive formatter.\n").
-spec collection_to_string(collection_types(FDM), fun((FDM) -> binary())) -> binary().
collection_to_string(Collection_type, To_string) ->
case Collection_type of
{dict, Key_type, Value_type} ->
<<<<<<<<"Dict("/utf8, (To_string(Key_type))/binary>>/binary,
", "/utf8>>/binary,
(To_string(Value_type))/binary>>/binary,
")"/utf8>>;
{list, Inner_type} ->
<<<<"List("/utf8, (To_string(Inner_type))/binary>>/binary,
")"/utf8>>
end.
-file("src/caffeine_lang/types.gleam", 397).
?DOC(" Generic modifier-to-string using a recursive formatter.\n").
-spec modifier_to_string(modifier_types(FDO), fun((FDO) -> binary())) -> binary().
modifier_to_string(Modifier_type, To_string) ->
case Modifier_type of
{optional, Inner_type} ->
<<<<"Optional("/utf8, (To_string(Inner_type))/binary>>/binary,
")"/utf8>>;
{defaulted, Inner_type@1, Default_val} ->
<<<<<<<<"Defaulted("/utf8, (To_string(Inner_type@1))/binary>>/binary,
", "/utf8>>/binary,
Default_val/binary>>/binary,
")"/utf8>>
end.
-file("src/caffeine_lang/types.gleam", 409).
?DOC(" Generic refinement-to-string using a recursive formatter.\n").
-spec refinement_to_string(refinement_types(FDQ), fun((FDQ) -> binary())) -> binary().
refinement_to_string(Refinement, To_string) ->
case Refinement of
{one_of, Typ, Set_vals} ->
<<<<<<(To_string(Typ))/binary, " { x | x in { "/utf8>>/binary,
(begin
_pipe = Set_vals,
_pipe@1 = gleam@set:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun gleam@string:compare/2
),
gleam@string:join(_pipe@2, <<", "/utf8>>)
end)/binary>>/binary,
" } }"/utf8>>;
{inclusive_range, Typ@1, Low, High} ->
<<<<<<<<<<(To_string(Typ@1))/binary, " { x | x in ( "/utf8>>/binary,
Low/binary>>/binary,
".."/utf8>>/binary,
High/binary>>/binary,
" ) }"/utf8>>
end.
-file("src/caffeine_lang/types.gleam", 546).
?DOC(false).
-spec parse_numeric_type(binary()) -> {ok, numeric_types()} | {error, nil}.
parse_numeric_type(Raw) ->
case Raw of
<<"Float"/utf8>> ->
{ok, float};
<<"Integer"/utf8>> ->
{ok, integer};
<<"Percentage"/utf8>> ->
{ok, percentage};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 533).
?DOC(false).
-spec parse_refinement_compatible_primitive(binary()) -> {ok, primitive_types()} |
{error, nil}.
parse_refinement_compatible_primitive(Raw) ->
case Raw of
<<"String"/utf8>> ->
{ok, string};
_ ->
_pipe = parse_numeric_type(Raw),
gleam@result:map(_pipe, fun(Field@0) -> {numeric_type, Field@0} end)
end.
-file("src/caffeine_lang/types.gleam", 557).
?DOC(false).
-spec parse_semantic_type(binary()) -> {ok, semantic_string_types()} |
{error, nil}.
parse_semantic_type(Raw) ->
case Raw of
<<"URL"/utf8>> ->
{ok, u_r_l};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 516).
?DOC(false).
-spec parse_primitive_type(binary()) -> {ok, primitive_types()} | {error, nil}.
parse_primitive_type(Raw) ->
case Raw of
<<"Boolean"/utf8>> ->
{ok, boolean};
<<"String"/utf8>> ->
{ok, string};
_ ->
_pipe = parse_numeric_type(Raw),
_pipe@1 = gleam@result:map(
_pipe,
fun(Field@0) -> {numeric_type, Field@0} end
),
gleam@result:lazy_or(
_pipe@1,
fun() -> _pipe@2 = parse_semantic_type(Raw),
gleam@result:map(
_pipe@2,
fun(Field@0) -> {semantic_type, Field@0} end
) end
)
end.
-file("src/caffeine_lang/types.gleam", 578).
-spec parse_list_type(binary(), fun((binary()) -> {ok, FER} | {error, nil})) -> {ok,
collection_types(FER)} |
{error, nil}.
parse_list_type(Inner_raw, Parse_inner) ->
case begin
_pipe = Inner_raw,
_pipe@1 = caffeine_lang@parsing_utils:paren_innerds_trimmed(_pipe),
Parse_inner(_pipe@1)
end of
{ok, Inner_type} ->
{ok, {list, Inner_type}};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 592).
-spec parse_dict_type(binary(), fun((binary()) -> {ok, FEX} | {error, nil})) -> {ok,
collection_types(FEX)} |
{error, nil}.
parse_dict_type(Inner_raw, Parse_inner) ->
case begin
_pipe = Inner_raw,
_pipe@1 = caffeine_lang@parsing_utils:paren_innerds_split_and_trimmed(
_pipe
),
gleam@list:map(_pipe@1, Parse_inner)
end of
[{ok, Key_type}, {ok, Value_type}] ->
{ok, {dict, Key_type, Value_type}};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 567).
?DOC(false).
-spec parse_collection_type(
binary(),
fun((binary()) -> {ok, FEL} | {error, nil})
) -> {ok, collection_types(FEL)} | {error, nil}.
parse_collection_type(Raw, Parse_inner) ->
case Raw of
<<"List"/utf8, Inside/binary>> ->
parse_list_type(Inside, Parse_inner);
<<"Dict"/utf8, Inside@1/binary>> ->
parse_dict_type(Inside@1, Parse_inner);
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 621).
-spec parse_optional_type(binary(), fun((binary()) -> {ok, FFL} | {error, nil})) -> {ok,
modifier_types(FFL)} |
{error, nil}.
parse_optional_type(Raw, Parse_inner) ->
case begin
_pipe = Raw,
_pipe@1 = caffeine_lang@parsing_utils:paren_innerds_trimmed(_pipe),
Parse_inner(_pipe@1)
end of
{ok, Inner_type} ->
{ok, {optional, Inner_type}};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 635).
-spec parse_defaulted_type(
binary(),
fun((binary()) -> {ok, FFR} | {error, nil}),
fun((FFR, binary()) -> {ok, nil} | {error, nil})
) -> {ok, modifier_types(FFR)} | {error, nil}.
parse_defaulted_type(Raw, Parse_inner, Validate_default) ->
gleam@result:'try'(
case caffeine_lang@parsing_utils:paren_innerds_split_and_trimmed(Raw) of
[Typ, Val] ->
{ok, {Typ, Val}};
_ ->
{error, nil}
end,
fun(_use0) ->
{Raw_inner_type, Raw_default_value} = _use0,
gleam@result:'try'(
Parse_inner(Raw_inner_type),
fun(Parsed_inner_type) ->
case Validate_default(Parsed_inner_type, Raw_default_value) of
{ok, _} ->
{ok,
{defaulted,
Parsed_inner_type,
Raw_default_value}};
{error, _} ->
{error, nil}
end
end
)
end
).
-file("src/caffeine_lang/types.gleam", 608).
?DOC(false).
-spec parse_modifier_type(
binary(),
fun((binary()) -> {ok, FFD} | {error, nil}),
fun((FFD, binary()) -> {ok, nil} | {error, nil})
) -> {ok, modifier_types(FFD)} | {error, nil}.
parse_modifier_type(Raw, Parse_inner, Validate_default) ->
case Raw of
<<"Optional"/utf8, Rest/binary>> ->
parse_optional_type(Rest, Parse_inner);
<<"Defaulted"/utf8, Rest@1/binary>> ->
parse_defaulted_type(Rest@1, Parse_inner, Validate_default);
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 708).
?DOC(
" Normalizes the refinement guard syntax, allowing flexible spacing around symbols.\n"
" Returns the normalized guard and the remaining string after it.\n"
" Valid: \"x | x in\", \"x| x in\", \"x |x in\", \"x|x in\" (flexible around |)\n"
" Invalid: \"xin\" (no space between words)\n"
).
-spec normalize_refinement_guard(binary()) -> {ok, {binary(), binary()}} |
{error, nil}.
normalize_refinement_guard(Raw) ->
case Raw of
<<"x | x in"/utf8, Rest/binary>> ->
{ok, {<<"x | x in"/utf8>>, Rest}};
<<"x| x in"/utf8, Rest@1/binary>> ->
{ok, {<<"x | x in"/utf8>>, Rest@1}};
<<"x |x in"/utf8, Rest@2/binary>> ->
{ok, {<<"x | x in"/utf8>>, Rest@2}};
<<"x|x in"/utf8, Rest@3/binary>> ->
{ok, {<<"x | x in"/utf8>>, Rest@3}};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 719).
-spec parse_one_of(
FGP,
binary(),
fun((FGP, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FGP)} | {error, nil}.
parse_one_of(Typ, Raw, Validate_set_value) ->
case gleam_stdlib:string_ends_with(Raw, <<"} }"/utf8>>) of
true ->
Set_vals = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_end(_pipe, 3),
gleam@string:trim(_pipe@1)
end,
Values = begin
_pipe@2 = Set_vals,
_pipe@3 = gleam@string:split(_pipe@2, <<","/utf8>>),
_pipe@4 = gleam@list:map(_pipe@3, fun gleam@string:trim/1),
gleam@list:filter(_pipe@4, fun(S) -> S /= <<""/utf8>> end)
end,
case Values of
[] ->
{error, nil};
_ ->
case gleam@list:try_each(
Values,
fun(_capture) -> Validate_set_value(Typ, _capture) end
) of
{ok, _} ->
Value_set = gleam@set:from_list(Values),
case gleam@set:size(Value_set) =:= erlang:length(
Values
) of
true ->
{ok, {one_of, Typ, Value_set}};
false ->
{error, nil}
end;
{error, _} ->
{error, nil}
end
end;
false ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 830).
?DOC(" Validates that Percentage range bounds are within [0.0, 100.0].\n").
-spec validate_percentage_range_bounds(binary(), binary()) -> {ok, nil} |
{error, nil}.
validate_percentage_range_bounds(Low, High) ->
case {gleam_stdlib:parse_float(Low), gleam_stdlib:parse_float(High)} of
{{ok, L}, {ok, H}} ->
case (L >= +0.0) andalso (H =< 100.0) of
true ->
{ok, nil};
false ->
{error, nil}
end;
{_, _} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 972).
?DOC(false).
-spec validate_numeric_value(numeric_types(), caffeine_lang@value:value()) -> {ok,
caffeine_lang@value:value()} |
{error, list(validation_error())}.
validate_numeric_value(Numeric, Val) ->
case {Numeric, Val} of
{integer, {int_value, _}} ->
{ok, Val};
{integer, _} ->
{error,
[{validation_error,
<<"Int"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]};
{float, {float_value, _}} ->
{ok, Val};
{float, _} ->
{error,
[{validation_error,
<<"Float"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]};
{percentage, {percentage_value, F}} ->
case (F >= +0.0) andalso (F =< 100.0) of
true ->
{ok, Val};
false ->
{error,
[{validation_error,
<<"Percentage (0.0 <= x <= 100.0)"/utf8>>,
gleam_stdlib:float_to_string(F),
[]}]}
end;
{percentage, {float_value, _}} ->
{error,
[{validation_error,
<<"Percentage (use % suffix, e.g. 99.9%)"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]};
{percentage, _} ->
{error,
[{validation_error,
<<"Percentage"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]}
end.
-file("src/caffeine_lang/types.gleam", 1046).
-spec validate_url(binary()) -> {ok, nil} | {error, nil}.
validate_url(S) ->
case gleam_stdlib:string_starts_with(S, <<"http://"/utf8>>) orelse gleam_stdlib:string_starts_with(
S,
<<"https://"/utf8>>
) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 1018).
-spec validate_semantic_value(
semantic_string_types(),
caffeine_lang@value:value()
) -> {ok, caffeine_lang@value:value()} | {error, list(validation_error())}.
validate_semantic_value(Typ, Val) ->
case {Typ, Val} of
{u_r_l, {string_value, Str}} ->
case validate_url(Str) of
{ok, nil} ->
{ok, Val};
{error, nil} ->
{error,
[{validation_error,
<<"URL (starting with http:// or https://)"/utf8>>,
Str,
[]}]}
end;
{u_r_l, _} ->
{error,
[{validation_error,
<<"String"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]}
end.
-file("src/caffeine_lang/types.gleam", 945).
-spec validate_primitive_value(primitive_types(), caffeine_lang@value:value()) -> {ok,
caffeine_lang@value:value()} |
{error, list(validation_error())}.
validate_primitive_value(Primitive, Val) ->
case {Primitive, Val} of
{boolean, {bool_value, _}} ->
{ok, Val};
{boolean, _} ->
{error,
[{validation_error,
<<"Bool"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]};
{string, {string_value, _}} ->
{ok, Val};
{string, _} ->
{error,
[{validation_error,
<<"String"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]};
{{numeric_type, Numeric_type}, _} ->
validate_numeric_value(Numeric_type, Val);
{{semantic_type, Semantic_type}, _} ->
validate_semantic_value(Semantic_type, Val)
end.
-file("src/caffeine_lang/types.gleam", 1316).
-spec parse_numeric_string(numeric_types(), binary()) -> {ok, float()} |
{error, nil}.
parse_numeric_string(Numeric, Value) ->
case Numeric of
integer ->
_pipe = gleam_stdlib:parse_int(Value),
gleam@result:map(_pipe, fun erlang:float/1);
float ->
gleam_stdlib:parse_float(Value);
percentage ->
Cleaned = case gleam_stdlib:string_ends_with(Value, <<"%"/utf8>>) of
true ->
gleam@string:drop_end(Value, 1);
false ->
Value
end,
gleam_stdlib:parse_float(Cleaned)
end.
-file("src/caffeine_lang/types.gleam", 1299).
?DOC(false).
-spec validate_numeric_default_value(numeric_types(), binary()) -> {ok, nil} |
{error, nil}.
validate_numeric_default_value(Numeric, Default_val) ->
case Numeric of
percentage ->
gleam@result:'try'(
parse_numeric_string(percentage, Default_val),
fun(F) -> case (F >= +0.0) andalso (F =< 100.0) of
true ->
{ok, nil};
false ->
{error, nil}
end end
);
_ ->
_pipe = parse_numeric_string(Numeric, Default_val),
gleam@result:replace(_pipe, nil)
end.
-file("src/caffeine_lang/types.gleam", 1334).
-spec validate_semantic_default_value(semantic_string_types(), binary()) -> {ok,
nil} |
{error, nil}.
validate_semantic_default_value(Typ, Default_val) ->
case Typ of
u_r_l ->
validate_url(Default_val)
end.
-file("src/caffeine_lang/types.gleam", 1282).
?DOC(false).
-spec validate_primitive_default_value(primitive_types(), binary()) -> {ok, nil} |
{error, nil}.
validate_primitive_default_value(Primitive, Default_val) ->
case Primitive of
boolean when (Default_val =:= <<"true"/utf8>>) orelse (Default_val =:= <<"false"/utf8>>) ->
{ok, nil};
boolean ->
{error, nil};
string ->
{ok, nil};
{numeric_type, Numeric_type} ->
validate_numeric_default_value(Numeric_type, Default_val);
{semantic_type, Semantic_type} ->
validate_semantic_default_value(Semantic_type, Default_val)
end.
-file("src/caffeine_lang/types.gleam", 1345).
?DOC(false).
-spec validate_modifier_default_value_recursive(
modifier_types(accepted_types()),
binary(),
fun((accepted_types(), binary()) -> {ok, nil} | {error, nil})
) -> {ok, nil} | {error, nil}.
validate_modifier_default_value_recursive(Modifier, Value, Validate_inner) ->
case Modifier of
{defaulted, Inner, _} ->
Validate_inner(Inner, Value);
{optional, _} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 908).
-spec validate_string_literal_or_defaulted(accepted_types(), binary()) -> {ok,
nil} |
{error, nil}.
validate_string_literal_or_defaulted(Typ, Value) ->
case Typ of
{primitive_type, Primitive} ->
validate_primitive_default_value(Primitive, Value);
{modifier_type, Modifier} ->
validate_modifier_default_value_recursive(
Modifier,
Value,
fun validate_string_literal_or_defaulted/2
);
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 1379).
?DOC(false).
-spec validate_in_range(numeric_types(), binary(), binary(), binary()) -> {ok,
nil} |
{error, list(validation_error())}.
validate_in_range(Numeric, Value_str, Low_str, High_str) ->
Type_name = numeric_type_to_string(Numeric),
case {parse_numeric_string(Numeric, Value_str),
parse_numeric_string(Numeric, Low_str),
parse_numeric_string(Numeric, High_str)} of
{{ok, Val}, {ok, Low}, {ok, High}} ->
case {Val >= Low, Val =< High} of
{true, true} ->
{ok, nil};
{_, _} ->
{error,
[{validation_error,
<<<<Low_str/binary, " <= x <= "/utf8>>/binary,
High_str/binary>>,
Value_str,
[]}]}
end;
{_, _, _} ->
{error, [{validation_error, Type_name, Value_str, []}]}
end.
-file("src/caffeine_lang/types.gleam", 816).
?DOC(" Validates that bounds are in valid order (low <= high) for a numeric type.\n").
-spec validate_bounds_order(binary(), binary(), binary()) -> {ok, nil} |
{error, nil}.
validate_bounds_order(Raw_typ, Low, High) ->
case parse_numeric_type(Raw_typ) of
{ok, Numeric} ->
_pipe = validate_in_range(Numeric, Low, Low, High),
gleam@result:replace_error(_pipe, nil);
{error, nil} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 760).
-spec parse_inclusive_range(
FGV,
binary(),
binary(),
fun((FGV, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FGV)} | {error, nil}.
parse_inclusive_range(Typ, Raw_typ, Raw, Validate_set_value) ->
case Raw_typ of
<<"Integer"/utf8>> ->
case gleam_stdlib:string_ends_with(Raw, <<") }"/utf8>>) of
true ->
Low_high_vals = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_end(_pipe, 3),
gleam@string:trim(_pipe@1)
end,
Values = begin
_pipe@2 = Low_high_vals,
_pipe@3 = gleam@string:split(_pipe@2, <<".."/utf8>>),
_pipe@4 = gleam@list:map(
_pipe@3,
fun gleam@string:trim/1
),
gleam@list:filter(
_pipe@4,
fun(S) -> S /= <<""/utf8>> end
)
end,
case Values of
[] ->
{error, nil};
[Low, High] ->
case gleam@list:try_each(
Values,
fun(_capture) ->
Validate_set_value(Typ, _capture)
end
) of
{ok, _} ->
case validate_bounds_order(
Raw_typ,
Low,
High
) of
{ok, _} ->
case Raw_typ of
<<"Percentage"/utf8>> ->
_pipe@5 = validate_percentage_range_bounds(
Low,
High
),
gleam@result:map(
_pipe@5,
fun(_) ->
{inclusive_range,
Typ,
Low,
High}
end
);
_ ->
{ok,
{inclusive_range,
Typ,
Low,
High}}
end;
{error, _} ->
{error, nil}
end;
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end;
false ->
{error, nil}
end;
<<"Float"/utf8>> ->
case gleam_stdlib:string_ends_with(Raw, <<") }"/utf8>>) of
true ->
Low_high_vals = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_end(_pipe, 3),
gleam@string:trim(_pipe@1)
end,
Values = begin
_pipe@2 = Low_high_vals,
_pipe@3 = gleam@string:split(_pipe@2, <<".."/utf8>>),
_pipe@4 = gleam@list:map(
_pipe@3,
fun gleam@string:trim/1
),
gleam@list:filter(
_pipe@4,
fun(S) -> S /= <<""/utf8>> end
)
end,
case Values of
[] ->
{error, nil};
[Low, High] ->
case gleam@list:try_each(
Values,
fun(_capture) ->
Validate_set_value(Typ, _capture)
end
) of
{ok, _} ->
case validate_bounds_order(
Raw_typ,
Low,
High
) of
{ok, _} ->
case Raw_typ of
<<"Percentage"/utf8>> ->
_pipe@5 = validate_percentage_range_bounds(
Low,
High
),
gleam@result:map(
_pipe@5,
fun(_) ->
{inclusive_range,
Typ,
Low,
High}
end
);
_ ->
{ok,
{inclusive_range,
Typ,
Low,
High}}
end;
{error, _} ->
{error, nil}
end;
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end;
false ->
{error, nil}
end;
<<"Percentage"/utf8>> ->
case gleam_stdlib:string_ends_with(Raw, <<") }"/utf8>>) of
true ->
Low_high_vals = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_end(_pipe, 3),
gleam@string:trim(_pipe@1)
end,
Values = begin
_pipe@2 = Low_high_vals,
_pipe@3 = gleam@string:split(_pipe@2, <<".."/utf8>>),
_pipe@4 = gleam@list:map(
_pipe@3,
fun gleam@string:trim/1
),
gleam@list:filter(
_pipe@4,
fun(S) -> S /= <<""/utf8>> end
)
end,
case Values of
[] ->
{error, nil};
[Low, High] ->
case gleam@list:try_each(
Values,
fun(_capture) ->
Validate_set_value(Typ, _capture)
end
) of
{ok, _} ->
case validate_bounds_order(
Raw_typ,
Low,
High
) of
{ok, _} ->
case Raw_typ of
<<"Percentage"/utf8>> ->
_pipe@5 = validate_percentage_range_bounds(
Low,
High
),
gleam@result:map(
_pipe@5,
fun(_) ->
{inclusive_range,
Typ,
Low,
High}
end
);
_ ->
{ok,
{inclusive_range,
Typ,
Low,
High}}
end;
{error, _} ->
{error, nil}
end;
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end;
false ->
{error, nil}
end;
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 680).
-spec do_parse_refinement(
FGH,
binary(),
binary(),
fun((FGH, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FGH)} | {error, nil}.
do_parse_refinement(Typ, Raw_typ, Raw, Validate_set_value) ->
Trimmed = gleam@string:trim(Raw),
case normalize_refinement_guard(Trimmed) of
{ok, {<<"x | x in"/utf8>>, Rest}} ->
Rest_trimmed = gleam@string:trim(Rest),
case Rest_trimmed of
<<"{"/utf8, Values_rest/binary>> ->
parse_one_of(Typ, Values_rest, Validate_set_value);
<<"("/utf8, Values_rest@1/binary>> ->
parse_inclusive_range(
Typ,
Raw_typ,
Values_rest@1,
Validate_set_value
);
_ ->
{error, nil}
end;
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 659).
?DOC(false).
-spec parse_refinement_type(
binary(),
fun((binary()) -> {ok, FFZ} | {error, nil}),
fun((FFZ, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FFZ)} | {error, nil}.
parse_refinement_type(Raw, Parse_inner, Validate_set_value) ->
case begin
_pipe = Raw,
gleam@string:split_once(_pipe, <<"{"/utf8>>)
end of
{ok, {Typ, Rest}} ->
Trimmed_typ = begin
_pipe@1 = Typ,
gleam@string:trim(_pipe@1)
end,
case Trimmed_typ of
<<"Boolean"/utf8>> ->
{error, nil};
<<"Dict"/utf8>> ->
{error, nil};
<<"List"/utf8>> ->
{error, nil};
<<"Optional"/utf8>> ->
{error, nil};
_ ->
gleam@result:'try'(
Parse_inner(Trimmed_typ),
fun(Parsed_typ) ->
do_parse_refinement(
Parsed_typ,
Trimmed_typ,
Rest,
Validate_set_value
)
end
)
end;
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 1438).
?DOC(false).
-spec resolve_primitive_to_string(
primitive_types(),
caffeine_lang@value:value(),
fun((binary()) -> binary())
) -> binary().
resolve_primitive_to_string(Primitive, Val, Resolve_string) ->
Str = case {Primitive, Val} of
{boolean, {bool_value, true}} ->
<<"true"/utf8>>;
{boolean, {bool_value, false}} ->
<<"false"/utf8>>;
{string, {string_value, S}} ->
S;
{{numeric_type, integer}, {int_value, I}} ->
erlang:integer_to_binary(I);
{{numeric_type, float}, {float_value, F}} ->
gleam_stdlib:float_to_string(F);
{{numeric_type, percentage}, {percentage_value, F@1}} ->
gleam_stdlib:float_to_string(F@1);
{{semantic_type, _}, {string_value, S@1}} ->
S@1;
{_, _} ->
caffeine_lang@value:to_string(Val)
end,
Resolve_string(Str).
-file("src/caffeine_lang/types.gleam", 1576).
?DOC(false).
-spec is_optional_or_defaulted(accepted_types()) -> boolean().
is_optional_or_defaulted(Typ) ->
case Typ of
{modifier_type, {optional, _}} ->
true;
{modifier_type, {defaulted, _, _}} ->
true;
{refinement_type, {one_of, Inner, _}} ->
is_optional_or_defaulted(Inner);
{record_type, _} ->
false;
_ ->
false
end.
-file("src/caffeine_lang/types.gleam", 1594).
?DOC(false).
-spec get_numeric_type(accepted_types()) -> numeric_types().
get_numeric_type(Typ) ->
case Typ of
{primitive_type, {numeric_type, Numeric}} ->
Numeric;
{primitive_type, {semantic_type, _}} ->
integer;
{primitive_type, string} ->
integer;
{primitive_type, boolean} ->
integer;
{collection_type, _} ->
integer;
{modifier_type, _} ->
integer;
{refinement_type, _} ->
integer;
{record_type, _} ->
integer
end.
-file("src/caffeine_lang/types.gleam", 1358).
?DOC(false).
-spec validate_refinement_default_value(
refinement_types(accepted_types()),
binary(),
fun((accepted_types(), binary()) -> {ok, nil} | {error, nil})
) -> {ok, nil} | {error, nil}.
validate_refinement_default_value(Refinement, Value, Validate_inner_default) ->
case Refinement of
{one_of, _, Allowed_values} ->
case gleam@set:contains(Allowed_values, Value) of
true ->
{ok, nil};
false ->
{error, nil}
end;
{inclusive_range, Inner, Low, High} ->
gleam@result:'try'(
Validate_inner_default(Inner, Value),
fun(_) ->
_pipe = validate_in_range(
get_numeric_type(Inner),
Value,
Low,
High
),
gleam@result:replace_error(_pipe, nil)
end
)
end.
-file("src/caffeine_lang/types.gleam", 883).
-spec validate_string_literal(accepted_types(), binary()) -> {ok, nil} |
{error, nil}.
validate_string_literal(Typ, Value) ->
case Typ of
{primitive_type, Primitive} ->
validate_primitive_default_value(Primitive, Value);
{refinement_type, Refinement} ->
validate_refinement_default_value(
Refinement,
Value,
fun validate_string_literal/2
);
{modifier_type, Modifier} ->
validate_modifier_default_value_recursive(
Modifier,
Value,
fun validate_string_literal/2
);
{collection_type, _} ->
{error, nil};
{record_type, _} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 865).
?DOC(
" Parser for primitives or Defaulted modifiers - used for refinement type inner types.\n"
" Only allows Integer, Float, String (not Boolean) or Defaulted with those types.\n"
).
-spec parse_primitive_or_defaulted(binary()) -> {ok, accepted_types()} |
{error, nil}.
parse_primitive_or_defaulted(Raw) ->
_pipe = parse_refinement_compatible_primitive(Raw),
_pipe@1 = gleam@result:map(
_pipe,
fun(Field@0) -> {primitive_type, Field@0} end
),
gleam@result:lazy_or(
_pipe@1,
fun() ->
_pipe@3 = parse_modifier_type(
Raw,
fun(Inner) ->
_pipe@2 = parse_refinement_compatible_primitive(Inner),
gleam@result:map(
_pipe@2,
fun(Field@0) -> {primitive_type, Field@0} end
)
end,
fun validate_string_literal/2
),
gleam@result:map(
_pipe@3,
fun(Field@0) -> {modifier_type, Field@0} end
)
end
).
-file("src/caffeine_lang/types.gleam", 846).
?DOC(
" Parser for primitives, collections (recursively nested), and refinements.\n"
" Used as the inner parser for both collection and modifier type parsing.\n"
).
-spec parse_primitive_or_collection(binary()) -> {ok, accepted_types()} |
{error, nil}.
parse_primitive_or_collection(Raw) ->
_pipe = parse_primitive_type(Raw),
_pipe@1 = gleam@result:map(
_pipe,
fun(Field@0) -> {primitive_type, Field@0} end
),
_pipe@3 = gleam@result:lazy_or(
_pipe@1,
fun() ->
_pipe@2 = parse_collection_type(
Raw,
fun parse_primitive_or_collection/1
),
gleam@result:map(
_pipe@2,
fun(Field@0) -> {collection_type, Field@0} end
)
end
),
gleam@result:lazy_or(
_pipe@3,
fun() ->
_pipe@4 = parse_refinement_type(
Raw,
fun parse_primitive_or_defaulted/1,
fun validate_string_literal_or_defaulted/2
),
gleam@result:map(
_pipe@4,
fun(Field@0) -> {refinement_type, Field@0} end
)
end
).
-file("src/caffeine_lang/types.gleam", 489).
?DOC(false).
-spec parse_accepted_type(binary()) -> {ok, accepted_types()} | {error, nil}.
parse_accepted_type(Raw) ->
_pipe = parse_primitive_type(Raw),
_pipe@1 = gleam@result:map(
_pipe,
fun(Field@0) -> {primitive_type, Field@0} end
),
_pipe@3 = gleam@result:lazy_or(
_pipe@1,
fun() ->
_pipe@2 = parse_collection_type(
Raw,
fun parse_primitive_or_collection/1
),
gleam@result:map(
_pipe@2,
fun(Field@0) -> {collection_type, Field@0} end
)
end
),
_pipe@5 = gleam@result:lazy_or(
_pipe@3,
fun() ->
_pipe@4 = parse_modifier_type(
Raw,
fun parse_primitive_or_collection/1,
fun validate_string_literal/2
),
gleam@result:map(
_pipe@4,
fun(Field@0) -> {modifier_type, Field@0} end
)
end
),
gleam@result:lazy_or(
_pipe@5,
fun() ->
_pipe@6 = parse_refinement_type(
Raw,
fun parse_primitive_or_defaulted/1,
fun validate_string_literal_or_defaulted/2
),
gleam@result:map(
_pipe@6,
fun(Field@0) -> {refinement_type, Field@0} end
)
end
).
-file("src/caffeine_lang/types.gleam", 1609).
-spec collection_try_each_inner(
collection_types(FKJ),
fun((FKJ) -> {ok, nil} | {error, FKL})
) -> {ok, nil} | {error, FKL}.
collection_try_each_inner(Collection, F) ->
case Collection of
{list, Inner} ->
F(Inner);
{dict, Key, Value} ->
gleam@result:'try'(F(Key), fun(_) -> F(Value) end)
end.
-file("src/caffeine_lang/types.gleam", 1622).
-spec collection_map_inner(collection_types(FKQ), fun((FKQ) -> FKQ)) -> collection_types(FKQ).
collection_map_inner(Collection, F) ->
case Collection of
{list, Inner} ->
{list, F(Inner)};
{dict, Key, Value} ->
{dict, F(Key), F(Value)}
end.
-file("src/caffeine_lang/types.gleam", 1632).
-spec modifier_try_each_inner(
modifier_types(FKT),
fun((FKT) -> {ok, nil} | {error, FKV})
) -> {ok, nil} | {error, FKV}.
modifier_try_each_inner(Modifier, F) ->
case Modifier of
{optional, Inner} ->
F(Inner);
{defaulted, Inner@1, _} ->
F(Inner@1)
end.
-file("src/caffeine_lang/types.gleam", 1642).
-spec modifier_map_inner(modifier_types(FLA), fun((FLA) -> FLA)) -> modifier_types(FLA).
modifier_map_inner(Modifier, F) ->
case Modifier of
{optional, Inner} ->
{optional, F(Inner)};
{defaulted, Inner@1, Default} ->
{defaulted, F(Inner@1), Default}
end.
-file("src/caffeine_lang/types.gleam", 1652).
-spec refinement_try_each_inner(
refinement_types(FLD),
fun((FLD) -> {ok, nil} | {error, FLF})
) -> {ok, nil} | {error, FLF}.
refinement_try_each_inner(Refinement, F) ->
case Refinement of
{one_of, Inner, _} ->
F(Inner);
{inclusive_range, Inner@1, _, _} ->
F(Inner@1)
end.
-file("src/caffeine_lang/types.gleam", 469).
?DOC(false).
-spec try_each_inner_parsed(
parsed_type(),
fun((parsed_type()) -> {ok, nil} | {error, FDW})
) -> {ok, nil} | {error, FDW}.
try_each_inner_parsed(Typ, F) ->
case Typ of
{parsed_primitive, _} ->
F(Typ);
{parsed_type_alias_ref, _} ->
F(Typ);
{parsed_collection, Collection} ->
collection_try_each_inner(Collection, F);
{parsed_modifier, Modifier} ->
modifier_try_each_inner(Modifier, F);
{parsed_refinement, Refinement} ->
refinement_try_each_inner(Refinement, F);
{parsed_record, Fields} ->
_pipe = maps:values(Fields),
gleam@list:try_each(_pipe, F)
end.
-file("src/caffeine_lang/types.gleam", 1543).
?DOC(false).
-spec try_each_inner(
accepted_types(),
fun((accepted_types()) -> {ok, nil} | {error, FKE})
) -> {ok, nil} | {error, FKE}.
try_each_inner(Typ, F) ->
case Typ of
{primitive_type, _} ->
F(Typ);
{collection_type, Collection} ->
collection_try_each_inner(Collection, F);
{modifier_type, Modifier} ->
modifier_try_each_inner(Modifier, F);
{refinement_type, Refinement} ->
refinement_try_each_inner(Refinement, F);
{record_type, Fields} ->
_pipe = maps:values(Fields),
gleam@list:try_each(_pipe, F)
end.
-file("src/caffeine_lang/types.gleam", 1662).
-spec refinement_map_inner(refinement_types(FLK), fun((FLK) -> FLK)) -> refinement_types(FLK).
refinement_map_inner(Refinement, F) ->
case Refinement of
{one_of, Inner, Values} ->
{one_of, F(Inner), Values};
{inclusive_range, Inner@1, Min, Max} ->
{inclusive_range, F(Inner@1), Min, Max}
end.
-file("src/caffeine_lang/types.gleam", 1558).
?DOC(false).
-spec map_inner(accepted_types(), fun((accepted_types()) -> accepted_types())) -> accepted_types().
map_inner(Typ, F) ->
case Typ of
{primitive_type, _} ->
F(Typ);
{collection_type, Collection} ->
{collection_type, collection_map_inner(Collection, F)};
{modifier_type, Modifier} ->
{modifier_type, modifier_map_inner(Modifier, F)};
{refinement_type, Refinement} ->
{refinement_type, refinement_map_inner(Refinement, F)};
{record_type, Fields} ->
{record_type, gleam@dict:map_values(Fields, fun(_, V) -> F(V) end)}
end.
-file("src/caffeine_lang/types.gleam", 1491).
-spec resolve_modifier_to_string(
modifier_types(accepted_types()),
caffeine_lang@value:value(),
fun((binary()) -> binary()),
fun((list(binary())) -> binary())
) -> {ok, binary()} | {error, binary()}.
resolve_modifier_to_string(Modifier, Val, Resolve_string, Resolve_list) ->
case Modifier of
{optional, Inner_type} ->
case Val of
nil_value ->
{ok, <<""/utf8>>};
_ ->
resolve_to_string(
Inner_type,
Val,
Resolve_string,
Resolve_list
)
end;
{defaulted, Inner_type@1, Default_val} ->
case Val of
nil_value ->
{ok, Resolve_string(Default_val)};
_ ->
resolve_to_string(
Inner_type@1,
Val,
Resolve_string,
Resolve_list
)
end
end.
-file("src/caffeine_lang/types.gleam", 1417).
?DOC(false).
-spec resolve_to_string(
accepted_types(),
caffeine_lang@value:value(),
fun((binary()) -> binary()),
fun((list(binary())) -> binary())
) -> {ok, binary()} | {error, binary()}.
resolve_to_string(Typ, Val, Resolve_string, Resolve_list) ->
case Typ of
{primitive_type, Primitive} ->
{ok, resolve_primitive_to_string(Primitive, Val, Resolve_string)};
{collection_type, Collection} ->
resolve_collection_to_string(Collection, Val, Resolve_list);
{modifier_type, Modifier} ->
resolve_modifier_to_string(
Modifier,
Val,
Resolve_string,
Resolve_list
);
{refinement_type, Refinement} ->
resolve_refinement_to_string(Refinement, Val, Resolve_string);
{record_type, _} ->
{error, <<"Record types cannot be template variables"/utf8>>}
end.
-file("src/caffeine_lang/types.gleam", 1053).
-spec validate_collection_value(
collection_types(accepted_types()),
caffeine_lang@value:value()
) -> {ok, caffeine_lang@value:value()} | {error, list(validation_error())}.
validate_collection_value(Collection, Val) ->
case Collection of
{dict, Key_type, Value_type} ->
case Val of
{dict_value, Dict_val} ->
_pipe = Dict_val,
_pipe@1 = maps:to_list(_pipe),
_pipe@4 = gleam@list:try_map(
_pipe@1,
fun(Pair) ->
{K, V} = Pair,
gleam@result:'try'(
begin
_pipe@2 = validate_value(
Key_type,
{string_value, K}
),
gleam@result:map_error(
_pipe@2,
fun(Errs) ->
gleam@list:map(
Errs,
fun(E) ->
{validation_error,
erlang:element(2, E),
erlang:element(3, E),
[K |
erlang:element(4, E)]}
end
)
end
)
end,
fun(_) ->
_pipe@3 = validate_value(Value_type, V),
gleam@result:map_error(
_pipe@3,
fun(Errs@1) ->
gleam@list:map(
Errs@1,
fun(E@1) ->
{validation_error,
erlang:element(2, E@1),
erlang:element(3, E@1),
[K |
erlang:element(
4,
E@1
)]}
end
)
end
)
end
)
end
),
gleam@result:map(_pipe@4, fun(_) -> Val end);
_ ->
{error,
[{validation_error,
<<"Dict"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]}
end;
{list, Inner_type} ->
case Val of
{list_value, List_val} ->
_pipe@5 = List_val,
_pipe@6 = gleam@list:index_map(
_pipe@5,
fun(V@1, I) -> {V@1, I} end
),
_pipe@8 = gleam@list:try_map(
_pipe@6,
fun(Pair@1) ->
{V@2, I@1} = Pair@1,
_pipe@7 = validate_value(Inner_type, V@2),
gleam@result:map_error(
_pipe@7,
fun(Errs@2) ->
gleam@list:map(
Errs@2,
fun(E@2) ->
{validation_error,
erlang:element(2, E@2),
erlang:element(3, E@2),
[erlang:integer_to_binary(I@1) |
erlang:element(4, E@2)]}
end
)
end
)
end
),
gleam@result:map(_pipe@8, fun(_) -> Val end);
_ ->
{error,
[{validation_error,
<<"List"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]}
end
end.
-file("src/caffeine_lang/types.gleam", 932).
?DOC(false).
-spec validate_value(accepted_types(), caffeine_lang@value:value()) -> {ok,
caffeine_lang@value:value()} |
{error, list(validation_error())}.
validate_value(Accepted_type, Val) ->
case Accepted_type of
{primitive_type, Primitive} ->
validate_primitive_value(Primitive, Val);
{collection_type, Collection} ->
validate_collection_value(Collection, Val);
{modifier_type, Modifier} ->
validate_modifier_value(Modifier, Val);
{refinement_type, Refinement} ->
validate_refinement_value(Refinement, Val);
{record_type, Fields} ->
validate_record_value(Fields, Val)
end.
-file("src/caffeine_lang/types.gleam", 1189).
-spec validate_modifier_value(
modifier_types(accepted_types()),
caffeine_lang@value:value()
) -> {ok, caffeine_lang@value:value()} | {error, list(validation_error())}.
validate_modifier_value(Modifier, Val) ->
Inner_type = case Modifier of
{optional, T} ->
T;
{defaulted, T@1, _} ->
T@1
end,
case Val of
nil_value ->
{ok, Val};
_ ->
validate_value(Inner_type, Val)
end.
-file("src/caffeine_lang/types.gleam", 453).
?DOC(false).
-spec parsed_type_to_string(parsed_type()) -> binary().
parsed_type_to_string(Parsed_type) ->
case Parsed_type of
{parsed_primitive, Primitive_type} ->
primitive_type_to_string(Primitive_type);
{parsed_collection, Collection_type} ->
collection_to_string(Collection_type, fun parsed_type_to_string/1);
{parsed_modifier, Modifier_type} ->
modifier_to_string(Modifier_type, fun parsed_type_to_string/1);
{parsed_refinement, Refinement_type} ->
refinement_to_string(Refinement_type, fun parsed_type_to_string/1);
{parsed_type_alias_ref, Name} ->
Name;
{parsed_record, Fields} ->
parsed_record_to_string(Fields)
end.
-file("src/caffeine_lang/types.gleam", 438).
?DOC(" Converts a parsed record type to its string representation.\n").
-spec parsed_record_to_string(gleam@dict:dict(binary(), parsed_type())) -> binary().
parsed_record_to_string(Fields) ->
Field_strs = begin
_pipe = Fields,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:map(
_pipe@2,
fun(Pair) ->
<<<<(erlang:element(1, Pair))/binary, ": "/utf8>>/binary,
(parsed_type_to_string(erlang:element(2, Pair)))/binary>>
end
)
end,
<<<<"{ "/utf8, (gleam@string:join(Field_strs, <<", "/utf8>>))/binary>>/binary,
" }"/utf8>>.
-file("src/caffeine_lang/types.gleam", 362).
?DOC(false).
-spec collection_type_to_string(collection_types(accepted_types())) -> binary().
collection_type_to_string(Collection_type) ->
collection_to_string(Collection_type, fun accepted_type_to_string/1).
-file("src/caffeine_lang/types.gleam", 321).
?DOC(false).
-spec accepted_type_to_string(accepted_types()) -> binary().
accepted_type_to_string(Accepted_type) ->
case Accepted_type of
{primitive_type, Primitive_type} ->
primitive_type_to_string(Primitive_type);
{collection_type, Collection_type} ->
collection_type_to_string(Collection_type);
{modifier_type, Modifier_type} ->
modifier_type_to_string(Modifier_type);
{refinement_type, Refinement_type} ->
refinement_type_to_string(Refinement_type);
{record_type, Fields} ->
record_type_to_string(Fields)
end.
-file("src/caffeine_lang/types.gleam", 370).
?DOC(false).
-spec modifier_type_to_string(modifier_types(accepted_types())) -> binary().
modifier_type_to_string(Modifier_type) ->
modifier_to_string(Modifier_type, fun accepted_type_to_string/1).
-file("src/caffeine_lang/types.gleam", 378).
?DOC(false).
-spec refinement_type_to_string(refinement_types(accepted_types())) -> binary().
refinement_type_to_string(Refinement) ->
refinement_to_string(Refinement, fun accepted_type_to_string/1).
-file("src/caffeine_lang/types.gleam", 428).
?DOC(" Converts a record type to its string representation.\n").
-spec record_type_to_string(gleam@dict:dict(binary(), accepted_types())) -> binary().
record_type_to_string(Fields) ->
Field_strs = begin
_pipe = Fields,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:map(
_pipe@2,
fun(Pair) ->
<<<<(erlang:element(1, Pair))/binary, ": "/utf8>>/binary,
(accepted_type_to_string(erlang:element(2, Pair)))/binary>>
end
)
end,
<<<<"{ "/utf8, (gleam@string:join(Field_strs, <<", "/utf8>>))/binary>>/binary,
" }"/utf8>>.
-file("src/caffeine_lang/types.gleam", 1121).
-spec validate_record_value(
gleam@dict:dict(binary(), accepted_types()),
caffeine_lang@value:value()
) -> {ok, caffeine_lang@value:value()} | {error, list(validation_error())}.
validate_record_value(Schema, Val) ->
case Val of
{dict_value, Dict_val} ->
Schema_keys = begin
_pipe = maps:keys(Schema),
gleam@set:from_list(_pipe)
end,
Val_keys = begin
_pipe@1 = maps:keys(Dict_val),
gleam@set:from_list(_pipe@1)
end,
Extra_keys = gleam@set:difference(Val_keys, Schema_keys),
gleam@bool:guard(
not gleam@set:is_empty(Extra_keys),
{error,
[{validation_error,
<<"only fields: "/utf8,
(begin
_pipe@2 = Schema_keys,
_pipe@3 = gleam@set:to_list(_pipe@2),
_pipe@4 = gleam@list:sort(
_pipe@3,
fun gleam@string:compare/2
),
gleam@string:join(_pipe@4, <<", "/utf8>>)
end)/binary>>,
<<"unexpected field(s): "/utf8,
(begin
_pipe@5 = Extra_keys,
_pipe@6 = gleam@set:to_list(_pipe@5),
_pipe@7 = gleam@list:sort(
_pipe@6,
fun gleam@string:compare/2
),
gleam@string:join(_pipe@7, <<", "/utf8>>)
end)/binary>>,
[]}]},
fun() -> _pipe@8 = Schema,
_pipe@9 = maps:to_list(_pipe@8),
_pipe@11 = gleam@list:try_map(
_pipe@9,
fun(Pair) ->
{Field_name, Field_type} = Pair,
case gleam_stdlib:map_get(Dict_val, Field_name) of
{ok, Field_val} ->
_pipe@10 = validate_value(
Field_type,
Field_val
),
gleam@result:map_error(
_pipe@10,
fun(Errs) ->
gleam@list:map(
Errs,
fun(E) ->
{validation_error,
erlang:element(2, E),
erlang:element(3, E),
[Field_name |
erlang:element(4, E)]}
end
)
end
);
{error, _} ->
case is_optional_or_defaulted(Field_type) of
true ->
{ok, nil_value};
false ->
{error,
[{validation_error,
accepted_type_to_string(
Field_type
),
<<"missing field"/utf8>>,
[Field_name]}]}
end
end
end
),
gleam@result:map(_pipe@11, fun(_) -> Val end) end
);
_ ->
{error,
[{validation_error,
<<"Record"/utf8>>,
caffeine_lang@value:classify(Val),
[]}]}
end.
-file("src/caffeine_lang/types.gleam", 1246).
?DOC(
" Converts a Value to its string representation based on the expected type.\n"
" Used internally for refinement validation and resolution.\n"
).
-spec value_to_type_string(accepted_types(), caffeine_lang@value:value()) -> {ok,
binary()} |
{error, list(validation_error())}.
value_to_type_string(Typ, Val) ->
case {Typ, Val} of
{{primitive_type, boolean}, {bool_value, true}} ->
{ok, <<"true"/utf8>>};
{{primitive_type, boolean}, {bool_value, false}} ->
{ok, <<"false"/utf8>>};
{{primitive_type, string}, {string_value, S}} ->
{ok, S};
{{primitive_type, {numeric_type, integer}}, {int_value, I}} ->
{ok, erlang:integer_to_binary(I)};
{{primitive_type, {numeric_type, float}}, {float_value, F}} ->
{ok, gleam_stdlib:float_to_string(F)};
{{primitive_type, {numeric_type, percentage}}, {percentage_value, F@1}} ->
{ok, gleam_stdlib:float_to_string(F@1)};
{{primitive_type, {semantic_type, _}}, {string_value, S@1}} ->
{ok, S@1};
{{modifier_type, {optional, Inner}}, nil_value} ->
_ = Inner,
{ok, <<""/utf8>>};
{{modifier_type, {defaulted, _, Default_val}}, nil_value} ->
{ok, Default_val};
{{modifier_type, {optional, Inner@1}}, _} ->
value_to_type_string(Inner@1, Val);
{{modifier_type, {defaulted, Inner@2, _}}, _} ->
value_to_type_string(Inner@2, Val);
{_, _} ->
{error,
[{validation_error,
accepted_type_to_string(Typ),
caffeine_lang@value:classify(Val),
[]}]}
end.
-file("src/caffeine_lang/types.gleam", 1205).
-spec validate_refinement_value(
refinement_types(accepted_types()),
caffeine_lang@value:value()
) -> {ok, caffeine_lang@value:value()} | {error, list(validation_error())}.
validate_refinement_value(Refinement, Val) ->
case Refinement of
{one_of, Inner_type, Allowed_values} ->
case value_to_type_string(Inner_type, Val) of
{ok, Str_val} ->
case gleam@set:contains(Allowed_values, Str_val) of
true ->
{ok, Val};
false ->
{error,
[{validation_error,
<<"one of: "/utf8,
(begin
_pipe = Allowed_values,
_pipe@1 = gleam@set:to_list(
_pipe
),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun gleam@string:compare/2
),
gleam@string:join(
_pipe@2,
<<", "/utf8>>
)
end)/binary>>,
Str_val,
[]}]}
end;
{error, Errs} ->
{error, Errs}
end;
{inclusive_range, Inner_type@1, Low, High} ->
gleam@result:'try'(
value_to_type_string(Inner_type@1, Val),
fun(As_str) ->
Numeric = get_numeric_type(Inner_type@1),
case validate_in_range(Numeric, As_str, Low, High) of
{ok, _} ->
{ok, Val};
{error, Errs@1} ->
{error, Errs@1}
end
end
)
end.
-file("src/caffeine_lang/types.gleam", 1456).
-spec resolve_collection_to_string(
collection_types(accepted_types()),
caffeine_lang@value:value(),
fun((list(binary())) -> binary())
) -> {ok, binary()} | {error, binary()}.
resolve_collection_to_string(Collection, Val, Resolve_list) ->
case Collection of
{dict, _, _} ->
{error,
<<<<"Unsupported templatized variable type: "/utf8,
(collection_type_to_string(Collection))/binary>>/binary,
". Dict support is pending, open an issue if this is a desired use case."/utf8>>};
{list, Inner_type} ->
case Val of
{list_value, Items} ->
Vals = begin
_pipe = Items,
gleam@list:map(
_pipe,
fun(Item) ->
case value_to_type_string(Inner_type, Item) of
{ok, S} ->
S;
{error, _} ->
caffeine_lang@value:to_string(Item)
end
end
)
end,
{ok, Resolve_list(Vals)};
_ ->
{error,
<<"Failed to resolve list values for type: "/utf8,
(collection_type_to_string(Collection))/binary>>}
end
end.
-file("src/caffeine_lang/types.gleam", 1513).
-spec resolve_refinement_to_string(
refinement_types(accepted_types()),
caffeine_lang@value:value(),
fun((binary()) -> binary())
) -> {ok, binary()} | {error, binary()}.
resolve_refinement_to_string(Refinement, Val, Resolve_string) ->
case Refinement of
{one_of, Inner_type, _} ->
case value_to_type_string(Inner_type, Val) of
{ok, S} ->
{ok, Resolve_string(S)};
{error, _} ->
{error,
<<"Unable to resolve OneOf refinement type value."/utf8>>}
end;
{inclusive_range, Inner_type@1, _, _} ->
case value_to_type_string(Inner_type@1, Val) of
{ok, S@1} ->
{ok, Resolve_string(S@1)};
{error, _} ->
{error,
<<"Unable to resolve InclusiveRange refinement type value."/utf8>>}
end
end.