Packages
caffeine_lang
6.2.2
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([refinement_all_type_metas/0, structured_all_type_metas/0, modifier_all_type_metas/0, collection_all_type_metas/0, semantic_type_meta/1, numeric_type_meta/1, primitive_all_type_metas/0, completable_type_metas/0, all_type_metas/0, semantic_type_to_string/1, numeric_type_to_string/1, primitive_type_to_string/1, refinement_type_to_string/1, modifier_type_to_string/1, collection_type_to_string/1, accepted_type_to_string/1, parsed_type_to_string/1, try_each_inner_parsed/2, validate_modifier_default_value_recursive/3, validate_numeric_default_value/2, validate_primitive_default_value/2, get_numeric_type/1, validate_in_range/4, validate_refinement_default_value/3, parse_numeric_type/1, parse_refinement_compatible_primitive/1, parse_modifier_type/3, parse_refinement_type/3, parse_collection_type/2, parse_semantic_type/1, parse_primitive_type/1, parse_accepted_type/1, is_optional_or_defaulted/1, validate_numeric_value/2, validate_value/2, parse_list_default_string/1, resolve_primitive_to_string/3, resolve_to_string/4, try_each_inner/2, map_inner/2]).
-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(FIT) :: {dict, FIT, FIT} | {list, FIT}.
-type modifier_types(FIU) :: {optional, FIU} | {defaulted, FIU, binary()}.
-type refinement_types(FIV) :: {one_of, FIV, gleam@set:set(binary())} |
{inclusive_range, FIV, 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", 277).
-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", 270).
?DOC(" Returns type metadata for all refinement types.\n").
-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", 297).
?DOC(" Returns type metadata for structured types (Record).\n").
-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", 250).
-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", 246).
?DOC(" Returns type metadata for all modifier types.\n").
-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", 226).
-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", 222).
?DOC(" Returns type metadata for all collection types.\n").
-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", 209).
?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", 202).
-spec semantic_all_type_metas() -> list(type_meta()).
semantic_all_type_metas() ->
[semantic_type_meta(u_r_l)].
-file("src/caffeine_lang/types.gleam", 176).
?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", 165).
-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", 144).
-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", 136).
?DOC(" Returns type metadata for all primitive types.\n").
-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", 127).
?DOC(
" Returns type metadata for types that can be used directly in type position.\n"
" Excludes refinement types (OneOf, InclusiveRange) since those are syntactic\n"
" modifiers applied to other types (e.g. `String { x | x in { a, b } }`),\n"
" not standalone type names a user would type.\n"
).
-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", 115).
?DOC(
" Returns all type metadata across all type categories.\n"
" Includes refinement types (OneOf, InclusiveRange) which are not standalone\n"
" types but are useful for documentation (hover, CLI `types` command).\n"
).
-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", 404).
?DOC(" Generic refinement-to-string using a recursive formatter.\n").
-spec refinement_to_string(refinement_types(FJS), fun((FJS) -> 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", 392).
?DOC(" Generic modifier-to-string using a recursive formatter.\n").
-spec modifier_to_string(modifier_types(FJQ), fun((FJQ) -> 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", 380).
?DOC(" Generic collection-to-string using a recursive formatter.\n").
-spec collection_to_string(collection_types(FJO), fun((FJO) -> 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", 349).
?DOC(false).
-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", 339).
?DOC(false).
-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", 328).
?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", 423).
?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", 373).
?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", 365).
?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", 357).
?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", 314).
?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", 448).
?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", 433).
?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", 1724).
-spec refinement_try_each_inner(
refinement_types(FRN),
fun((FRN) -> {ok, nil} | {error, FRP})
) -> {ok, nil} | {error, FRP}.
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", 1704).
-spec modifier_try_each_inner(
modifier_types(FRD),
fun((FRD) -> {ok, nil} | {error, FRF})
) -> {ok, nil} | {error, FRF}.
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", 1681).
-spec collection_try_each_inner(
collection_types(FQT),
fun((FQT) -> {ok, nil} | {error, FQV})
) -> {ok, nil} | {error, FQV}.
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", 464).
?DOC(false).
-spec try_each_inner_parsed(
parsed_type(),
fun((parsed_type()) -> {ok, nil} | {error, FJY})
) -> {ok, nil} | {error, FJY}.
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", 1371).
?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", 1072).
-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", 1360).
-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", 1342).
-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", 1325).
?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", 1308).
?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", 928).
-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", 901).
?DOC(
" Validates a list default like \"[200, 404]\" or \"[a, b]\" for a `List(inner)` type.\n"
" The default must be bracket-delimited, and every element must be valid for the\n"
" inner type per the supplied element validator.\n"
).
-spec validate_list_default_value(
accepted_types(),
binary(),
fun((accepted_types(), binary()) -> {ok, nil} | {error, nil})
) -> {ok, nil} | {error, nil}.
validate_list_default_value(Inner, Value, Validate_inner) ->
Trimmed = gleam@string:trim(Value),
case {gleam_stdlib:string_starts_with(Trimmed, <<"["/utf8>>),
gleam_stdlib:string_ends_with(Trimmed, <<"]"/utf8>>)} of
{true, true} ->
Body = begin
_pipe = Trimmed,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
_pipe@2 = gleam@string:drop_end(_pipe@1, 1),
gleam@string:trim(_pipe@2)
end,
case Body of
<<""/utf8>> ->
{ok, nil};
_ ->
_pipe@3 = Body,
_pipe@4 = gleam@string:split(_pipe@3, <<","/utf8>>),
_pipe@5 = gleam@list:map(_pipe@4, fun gleam@string:trim/1),
gleam@list:try_each(
_pipe@5,
fun(_capture) -> Validate_inner(Inner, _capture) end
)
end;
{_, _} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 1666).
?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", 1405).
?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", 1384).
?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", 872).
-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, {list, Inner}} ->
validate_list_default_value(
Inner,
Value,
fun validate_string_literal/2
);
{collection_type, _} ->
{error, nil};
{record_type, _} ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 541).
?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", 528).
?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", 630).
-spec parse_defaulted_type(
binary(),
fun((binary()) -> {ok, FLT} | {error, nil}),
fun((FLT, binary()) -> {ok, nil} | {error, nil})
) -> {ok, modifier_types(FLT)} | {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", 616).
-spec parse_optional_type(binary(), fun((binary()) -> {ok, FLN} | {error, nil})) -> {ok,
modifier_types(FLN)} |
{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", 603).
?DOC(false).
-spec parse_modifier_type(
binary(),
fun((binary()) -> {ok, FLF} | {error, nil}),
fun((FLF, binary()) -> {ok, nil} | {error, nil})
) -> {ok, modifier_types(FLF)} | {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", 854).
?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", 819).
?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", 805).
?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", 749).
-spec parse_inclusive_range(
FMX,
binary(),
binary(),
fun((FMX, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FMX)} | {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", 708).
-spec parse_one_of(
FMR,
binary(),
fun((FMR, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FMR)} | {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", 697).
?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", 669).
-spec do_parse_refinement(
FMJ,
binary(),
binary(),
fun((FMJ, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FMJ)} | {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", 654).
?DOC(false).
-spec parse_refinement_type(
binary(),
fun((binary()) -> {ok, FMB} | {error, nil}),
fun((FMB, binary()) -> {ok, nil} | {error, nil})
) -> {ok, refinement_types(FMB)} | {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,
gleam@result:'try'(
Parse_inner(Trimmed_typ),
fun(Parsed_typ) ->
do_parse_refinement(
Parsed_typ,
Trimmed_typ,
Rest,
Validate_set_value
)
end
);
_ ->
{error, nil}
end.
-file("src/caffeine_lang/types.gleam", 587).
-spec parse_dict_type(binary(), fun((binary()) -> {ok, FKZ} | {error, nil})) -> {ok,
collection_types(FKZ)} |
{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", 573).
-spec parse_list_type(binary(), fun((binary()) -> {ok, FKT} | {error, nil})) -> {ok,
collection_types(FKT)} |
{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", 562).
?DOC(false).
-spec parse_collection_type(
binary(),
fun((binary()) -> {ok, FKN} | {error, nil})
) -> {ok, collection_types(FKN)} | {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", 552).
?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", 511).
?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", 835).
?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", 484).
?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", 1648).
?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", 1272).
?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", 1231).
-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", 1044).
-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", 998).
?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", 965).
-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, {external_indicator_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", 1147).
-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", 1215).
-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", 1079).
-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", 952).
?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", 1585).
-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.
-file("src/caffeine_lang/types.gleam", 1567).
?DOC(false).
-spec parse_list_default_string(binary()) -> list(binary()).
parse_list_default_string(Default_val) ->
Trimmed = gleam@string:trim(Default_val),
case {gleam_stdlib:string_starts_with(Trimmed, <<"["/utf8>>),
gleam_stdlib:string_ends_with(Trimmed, <<"]"/utf8>>)} of
{true, true} ->
Inner = begin
_pipe = Trimmed,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
_pipe@2 = gleam@string:drop_end(_pipe@1, 1),
gleam@string:trim(_pipe@2)
end,
case Inner of
<<""/utf8>> ->
[];
_ ->
_pipe@3 = Inner,
_pipe@4 = gleam@string:split(_pipe@3, <<","/utf8>>),
gleam@list:map(_pipe@4, fun gleam@string:trim/1)
end;
{_, _} ->
[Default_val]
end.
-file("src/caffeine_lang/types.gleam", 1549).
?DOC(
" Turns a Defaulted's stored default-string into a resolved output. Routes through\n"
" resolve_list when the inner type is a List so list-typed defaults render as\n"
" `IN (...)` rather than getting concatenated as one opaque string. Other types\n"
" fall through to resolve_string (the historical behavior).\n"
).
-spec resolve_default_value_to_string(
accepted_types(),
binary(),
fun((binary()) -> binary()),
fun((list(binary())) -> binary())
) -> {ok, binary()} | {error, binary()}.
resolve_default_value_to_string(
Inner_type,
Default_val,
Resolve_string,
Resolve_list
) ->
case Inner_type of
{collection_type, {list, _}} ->
{ok, Resolve_list(parse_list_default_string(Default_val))};
_ ->
{ok, Resolve_string(Default_val)}
end.
-file("src/caffeine_lang/types.gleam", 1482).
-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", 1464).
?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", 1517).
-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 ->
resolve_default_value_to_string(
Inner_type@1,
Default_val,
Resolve_string,
Resolve_list
);
_ ->
resolve_to_string(
Inner_type@1,
Val,
Resolve_string,
Resolve_list
)
end
end.
-file("src/caffeine_lang/types.gleam", 1443).
?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", 1615).
?DOC(false).
-spec try_each_inner(
accepted_types(),
fun((accepted_types()) -> {ok, nil} | {error, FQO})
) -> {ok, nil} | {error, FQO}.
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", 1734).
-spec refinement_map_inner(refinement_types(FRU), fun((FRU) -> FRU)) -> refinement_types(FRU).
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", 1714).
-spec modifier_map_inner(modifier_types(FRK), fun((FRK) -> FRK)) -> modifier_types(FRK).
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", 1694).
-spec collection_map_inner(collection_types(FRA), fun((FRA) -> FRA)) -> collection_types(FRA).
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", 1630).
?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.