Current section

Files

Jump to
oaspec src oaspec@internal@codegen@guards.erl
Raw

src/oaspec@internal@codegen@guards.erl

-module(oaspec@internal@codegen@guards).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/internal/codegen/guards.gleam").
-export([schema_has_validator/2, generate/1]).
-export_type([parsed_chunk/0, constraint_types/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.
?MODULEDOC(false).
-type parsed_chunk() :: {parsed_chunk,
binary(),
binary(),
binary(),
binary(),
binary(),
binary()}.
-type constraint_types() :: {constraint_types,
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean()}.
-file("src/oaspec/internal/codegen/guards.gleam", 281).
?DOC(false).
-spec rsplit_once_on_close_brace(binary()) -> {ok, {binary(), binary()}} |
{error, nil}.
rsplit_once_on_close_brace(S) ->
Needle = <<"\n}\n"/utf8>>,
case gleam@string:split(S, Needle) of
[_] ->
{error, nil};
Parts ->
case lists:reverse(Parts) of
[] ->
{error, nil};
[Last_part | Rev_rest] ->
Body = begin
_pipe = lists:reverse(Rev_rest),
gleam@string:join(_pipe, Needle)
end,
{ok, {Body, Last_part}}
end
end.
-file("src/oaspec/internal/codegen/guards.gleam", 251).
?DOC(false).
-spec parse_function_chunk_strict(binary()) -> {ok, parsed_chunk()} |
{error, nil}.
parse_function_chunk_strict(Chunk) ->
gleam@result:'try'(
gleam@string:split_once(Chunk, <<"("/utf8>>),
fun(_use0) ->
{Name, After_open_paren} = _use0,
gleam@result:'try'(
gleam@string:split_once(After_open_paren, <<") -> "/utf8>>),
fun(_use0@1) ->
{Param_decl, After_arrow} = _use0@1,
gleam@result:'try'(
gleam@string:split_once(After_arrow, <<" {\n"/utf8>>),
fun(_use0@2) ->
{Return_type, After_open_brace} = _use0@2,
gleam@result:'try'(
rsplit_once_on_close_brace(After_open_brace),
fun(_use0@3) ->
{Body, Trailing} = _use0@3,
{ok,
{parsed_chunk,
Name,
Param_decl,
Return_type,
Body,
Trailing,
Chunk}}
end
)
end
)
end
)
end
).
-file("src/oaspec/internal/codegen/guards.gleam", 233).
?DOC(false).
-spec parse_function_chunk(binary()) -> parsed_chunk().
parse_function_chunk(Chunk) ->
Fallback = {parsed_chunk,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
Chunk},
_pipe = parse_function_chunk_strict(Chunk),
gleam@result:unwrap(_pipe, Fallback).
-file("src/oaspec/internal/codegen/guards.gleam", 348).
?DOC(false).
-spec per_field_validator_suffixes() -> list(binary()).
per_field_validator_suffixes() ->
[<<"_length"/utf8>>,
<<"_pattern"/utf8>>,
<<"_range"/utf8>>,
<<"_exclusive"/utf8>>,
<<"_multiple_of"/utf8>>,
<<"_count"/utf8>>,
<<"_unique"/utf8>>].
-file("src/oaspec/internal/codegen/guards.gleam", 338).
?DOC(false).
-spec is_dedupable(parsed_chunk()) -> boolean().
is_dedupable(Chunk) ->
gleam@bool:guard(
not gleam_stdlib:string_starts_with(
erlang:element(2, Chunk),
<<"validate_"/utf8>>
),
false,
fun() ->
gleam@list:any(
per_field_validator_suffixes(),
fun(Suffix) ->
gleam_stdlib:string_ends_with(
erlang:element(2, Chunk),
Suffix
)
end
)
end
).
-file("src/oaspec/internal/codegen/guards.gleam", 314).
?DOC(false).
-spec build_body_to_canonical_name_map(list(parsed_chunk())) -> gleam@dict:dict(binary(), binary()).
build_body_to_canonical_name_map(Parsed) ->
gleam@list:fold(
Parsed,
maps:new(),
fun(Acc, Chunk) -> case is_dedupable(Chunk) of
false ->
Acc;
true ->
case gleam_stdlib:map_get(Acc, erlang:element(5, Chunk)) of
{error, nil} ->
gleam@dict:insert(
Acc,
erlang:element(5, Chunk),
erlang:element(2, Chunk)
);
{ok, Existing} ->
case gleam@string:compare(
erlang:element(2, Chunk),
Existing
) of
lt ->
gleam@dict:insert(
Acc,
erlang:element(5, Chunk),
erlang:element(2, Chunk)
);
_ ->
Acc
end
end
end end
).
-file("src/oaspec/internal/codegen/guards.gleam", 376).
?DOC(false).
-spec emit_delegator(parsed_chunk(), binary()) -> binary().
emit_delegator(Chunk, Canonical_name) ->
<<<<<<<<<<<<<<<<(erlang:element(2, Chunk))/binary, "("/utf8>>/binary,
(erlang:element(3, Chunk))/binary>>/binary,
") -> "/utf8>>/binary,
(erlang:element(4, Chunk))/binary>>/binary,
" {\n "/utf8>>/binary,
Canonical_name/binary>>/binary,
"(value)\n}\n"/utf8>>/binary,
(erlang:element(6, Chunk))/binary>>.
-file("src/oaspec/internal/codegen/guards.gleam", 358).
?DOC(false).
-spec rewrite_chunk_if_duplicate(
parsed_chunk(),
gleam@dict:dict(binary(), binary())
) -> binary().
rewrite_chunk_if_duplicate(Chunk, Canonical_by_body) ->
case gleam_stdlib:map_get(Canonical_by_body, erlang:element(5, Chunk)) of
{error, nil} ->
erlang:element(7, Chunk);
{ok, Canonical_name} ->
case Canonical_name =:= erlang:element(2, Chunk) of
true ->
erlang:element(7, Chunk);
false ->
emit_delegator(Chunk, Canonical_name)
end
end.
-file("src/oaspec/internal/codegen/guards.gleam", 177).
?DOC(false).
-spec dedupe_field_validator_definitions(binary()) -> binary().
dedupe_field_validator_definitions(Source) ->
case gleam@string:split(Source, <<"\npub fn "/utf8>>) of
[] ->
Source;
[_] ->
Source;
[Head | Raw_chunks] ->
Parsed = gleam@list:map(Raw_chunks, fun parse_function_chunk/1),
Canonical_by_body = build_body_to_canonical_name_map(Parsed),
Rewritten = gleam@list:map(
Parsed,
fun(P) -> rewrite_chunk_if_duplicate(P, Canonical_by_body) end
),
<<Head/binary,
(erlang:list_to_binary(
gleam@list:map(
Rewritten,
fun(C) -> <<"\npub fn "/utf8, C/binary>> end
)
))/binary>>
end.
-file("src/oaspec/internal/codegen/guards.gleam", 744).
?DOC(false).
-spec character_word(integer()) -> binary().
character_word(N) ->
case N of
1 ->
<<"character"/utf8>>;
_ ->
<<"characters"/utf8>>
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1390).
?DOC(false).
-spec guard_function_name(binary(), binary(), binary()) -> binary().
guard_function_name(Schema_name, Prop_name, Constraint) ->
Base = oaspec@internal@util@naming:to_snake_case(Schema_name),
case Prop_name of
<<""/utf8>> ->
<<<<<<"validate_"/utf8, Base/binary>>/binary, "_"/utf8>>/binary,
Constraint/binary>>;
_ ->
<<<<<<<<<<"validate_"/utf8, Base/binary>>/binary, "_"/utf8>>/binary,
(oaspec@internal@util@naming:to_snake_case(Prop_name))/binary>>/binary,
"_"/utf8>>/binary,
Constraint/binary>>
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1409).
?DOC(false).
-spec field_label(binary()) -> binary().
field_label(Prop_name) ->
case Prop_name of
<<""/utf8>> ->
<<""/utf8>>;
_ ->
<<"."/utf8, Prop_name/binary>>
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1417).
?DOC(false).
-spec gleam_string_literal(binary()) -> binary().
gleam_string_literal(Value) ->
Escaped = begin
_pipe = Value,
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"\n"/utf8>>, <<"\\n"/utf8>>),
_pipe@4 = gleam@string:replace(_pipe@3, <<"\r"/utf8>>, <<"\\r"/utf8>>),
gleam@string:replace(_pipe@4, <<"\t"/utf8>>, <<"\\t"/utf8>>)
end,
<<<<"\""/utf8, Escaped/binary>>/binary, "\""/utf8>>.
-file("src/oaspec/internal/codegen/guards.gleam", 1432).
?DOC(false).
-spec emit_validation_failure_type(gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree().
emit_validation_failure_type(Sb) ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:doc_comment(
_pipe,
<<"A single field-level validation failure."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:doc_comment(
_pipe@1,
<<"Composite validators return `List(ValidationFailure)` so callers can build structured 422 bodies and clients can branch per-field instead of parsing prose messages. `field` is the JSON property name (empty for top-level constraints), `code` is a JSON Schema keyword like `minLength` / `maximum` / `pattern`, and `message` is human-readable."/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:line(
_pipe@2,
<<"pub type ValidationFailure {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<"ValidationFailure(field: String, code: String, message: String)"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:line(_pipe@4, <<"}"/utf8>>),
_pipe@6 = oaspec@internal@util@string_extra:blank_line(_pipe@5),
_pipe@7 = oaspec@internal@util@string_extra:doc_comment(
_pipe@6,
<<"Encode a `ValidationFailure` as JSON for emitting 422 response bodies."/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:line(
_pipe@7,
<<"pub fn validation_failure_to_json(failure: ValidationFailure) -> json.Json {"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
1,
<<"json.object(["/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
2,
<<"#(\"field\", json.string(failure.field)),"/utf8>>
),
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
2,
<<"#(\"code\", json.string(failure.code)),"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"#(\"message\", json.string(failure.message)),"/utf8>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
1,
<<"])"/utf8>>
),
_pipe@14 = oaspec@internal@util@string_extra:line(_pipe@13, <<"}"/utf8>>),
oaspec@internal@util@string_extra:blank_line(_pipe@14).
-file("src/oaspec/internal/codegen/guards.gleam", 1462).
?DOC(false).
-spec validation_failure_literal(binary(), binary(), binary()) -> binary().
validation_failure_literal(Field, Code, Message) ->
<<<<<<<<<<<<"Error(ValidationFailure(field: "/utf8,
(gleam_string_literal(Field))/binary>>/binary,
", code: "/utf8>>/binary,
(gleam_string_literal(Code))/binary>>/binary,
", message: "/utf8>>/binary,
(gleam_string_literal(Message))/binary>>/binary,
"))"/utf8>>.
-file("src/oaspec/internal/codegen/guards.gleam", 752).
?DOC(false).
-spec generate_string_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_string_guard(Sb, Schema_name, Prop_name, Min_length, Max_length) ->
case {Min_length, Max_length} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"minLength"/utf8>>,
<<<<<<"must be at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" "/utf8>>/binary,
(character_word(Min))/binary>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"maxLength"/utf8>>,
<<<<<<"must be at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" "/utf8>>/binary,
(character_word(Max))/binary>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate string length for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: String) -> Result(String, ValidationFailure) {"/utf8>>
)
end,
Sb@3 = begin
_pipe@2 = Sb@2,
oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<"let len = string.length(value)"/utf8>>
)
end,
Sb@4 = case {Min_length, Max_length} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@3 = Sb@3,
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"True -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@11 = Sb@3,
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"True -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@14 = oaspec@internal@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@15 = Sb@3,
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"True -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@18 = oaspec@internal@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@18,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@3
end,
_pipe@19 = Sb@4,
_pipe@20 = oaspec@internal@util@string_extra:line(
_pipe@19,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 829).
?DOC(false).
-spec generate_integer_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_guard(Sb, Schema_name, Prop_name, Minimum, Maximum) ->
case {Minimum, Maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"minimum"/utf8>>,
<<"must be at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"maximum"/utf8>>,
<<"must be at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, ValidationFailure) {"/utf8>>
)
end,
Sb@3 = case {Minimum, Maximum} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"True -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"False ->"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
4,
<<"True -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"True -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@13,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
2,
<<"True -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@17,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@internal@util@string_extra:line(
_pipe@18,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 902).
?DOC(false).
-spec generate_float_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float()),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_guard(Sb, Schema_name, Prop_name, Minimum, Maximum) ->
case {Minimum, Maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"minimum"/utf8>>,
<<"must be at least "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"maximum"/utf8>>,
<<"must be at most "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, ValidationFailure) {"/utf8>>
)
end,
Sb@3 = case {Minimum, Maximum} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"True -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"False ->"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
4,
<<"True -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"True -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@13,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
2,
<<"True -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@17,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@internal@util@string_extra:line(
_pipe@18,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 975).
?DOC(false).
-spec generate_integer_exclusive_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_exclusive_guard(
Sb,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
) ->
case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"exclusiveMinimum"/utf8>>,
<<"must be greater than "/utf8,
(erlang:integer_to_binary(Min))/binary>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"exclusiveMaximum"/utf8>>,
<<"must be less than "/utf8,
(erlang:integer_to_binary(Max))/binary>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer exclusive range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, ValidationFailure) {"/utf8>>
)
end,
Sb@3 = case {Exclusive_minimum, Exclusive_maximum} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"False -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True ->"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
4,
<<"False -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"True -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"False -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@13,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
2,
<<"False -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@17,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@internal@util@string_extra:line(
_pipe@18,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1049).
?DOC(false).
-spec generate_integer_multiple_of_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_multiple_of_guard(Sb, Schema_name, Prop_name, Multiple_of) ->
case Multiple_of of
none ->
Sb;
{some, M} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Failure = validation_failure_literal(
Prop_name,
<<"multipleOf"/utf8>>,
<<"must be a multiple of "/utf8,
(erlang:integer_to_binary(M))/binary>>
),
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer multipleOf for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, ValidationFailure) {"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value % "/utf8, (erlang:integer_to_binary(M))/binary>>/binary,
" == 0 {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"False -> "/utf8, Failure/binary>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<"}"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:line(
_pipe@6,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@7)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1088).
?DOC(false).
-spec generate_float_exclusive_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float()),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_exclusive_guard(
Sb,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
) ->
case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"exclusiveMinimum"/utf8>>,
<<"must be greater than "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"exclusiveMaximum"/utf8>>,
<<"must be less than "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float exclusive range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, ValidationFailure) {"/utf8>>
)
end,
Sb@3 = case {Exclusive_minimum, Exclusive_maximum} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"False -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True ->"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
4,
<<"False -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"True -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"False -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@13,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
2,
<<"False -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@17,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@internal@util@string_extra:line(
_pipe@18,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1162).
?DOC(false).
-spec generate_float_multiple_of_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_multiple_of_guard(Sb, Schema_name, Prop_name, Multiple_of) ->
case Multiple_of of
none ->
Sb;
{some, M} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Failure = validation_failure_literal(
Prop_name,
<<"multipleOf"/utf8>>,
<<"must be a multiple of "/utf8,
(gleam_stdlib:float_to_string(M))/binary>>
),
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float multipleOf for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, ValidationFailure) {"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<<<"let remainder = value -. float.truncate(value /. "/utf8,
(gleam_stdlib:float_to_string(M))/binary>>/binary,
" |> int.to_float) *. "/utf8>>/binary,
(gleam_stdlib:float_to_string(M))/binary>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<"case remainder == 0.0 || remainder == -0.0 {"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"False -> "/utf8, Failure/binary>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
1,
<<"}"/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:line(
_pipe@7,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@8)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1208).
?DOC(false).
-spec generate_list_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_list_guard(Sb, Schema_name, Prop_name, Min_items, Max_items) ->
case {Min_items, Max_items} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"minItems"/utf8>>,
<<<<"must have at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" items"/utf8>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"maxItems"/utf8>>,
<<<<"must have at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" items"/utf8>>
)
end,
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate list length for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: List(a)) -> Result(List(a), ValidationFailure) {"/utf8>>
)
end,
Sb@3 = begin
_pipe@2 = Sb@2,
oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<"let len = list.length(value)"/utf8>>
)
end,
Sb@4 = case {Min_items, Max_items} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@3 = Sb@3,
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"True -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@11 = Sb@3,
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"True -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@14 = oaspec@internal@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@15 = Sb@3,
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"True -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@18 = oaspec@internal@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@18,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@3
end,
_pipe@19 = Sb@4,
_pipe@20 = oaspec@internal@util@string_extra:line(
_pipe@19,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1284).
?DOC(false).
-spec generate_unique_items_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
boolean()
) -> gleam@string_tree:string_tree().
generate_unique_items_guard(Sb, Schema_name, Prop_name, Unique_items) ->
gleam@bool:guard(
not Unique_items,
Sb,
fun() ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"unique"/utf8>>
),
Failure = validation_failure_literal(
Prop_name,
<<"uniqueItems"/utf8>>,
<<"items must be unique"/utf8>>
),
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate unique items for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: List(a)) -> Result(List(a), ValidationFailure) {"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<"case list.length(value) == list.length(list.unique(value)) {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"False -> "/utf8, Failure/binary>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<"}"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:line(
_pipe@6,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@7)
end
).
-file("src/oaspec/internal/codegen/guards.gleam", 1318).
?DOC(false).
-spec generate_properties_count_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_properties_count_guard(
Sb,
Schema_name,
Prop_name,
Min_properties,
Max_properties
) ->
case {Min_properties, Max_properties} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"properties"/utf8>>
),
Min_failure = fun(Min) ->
validation_failure_literal(
Prop_name,
<<"minProperties"/utf8>>,
<<<<"must have at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" properties"/utf8>>
)
end,
Max_failure = fun(Max) ->
validation_failure_literal(
Prop_name,
<<"maxProperties"/utf8>>,
<<<<"must have at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" properties"/utf8>>
)
end,
Sb@1 = begin
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate property count for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Dict(k, v)) -> Result(Dict(k, v), ValidationFailure) {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<"let count = dict.size(value)"/utf8>>
)
end,
Sb@2 = case {Min_properties, Max_properties} of
{{some, Min@1}, {some, Max@1}} ->
_pipe@3 = Sb@1,
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<<<"case count < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
2,
<<"True -> "/utf8, (Min_failure(Min@1))/binary>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case count > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<"True -> "/utf8, (Max_failure(Max@1))/binary>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<"}"/utf8>>
);
{{some, Min@2}, none} ->
_pipe@11 = Sb@1,
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
1,
<<<<"case count < "/utf8,
(erlang:integer_to_binary(Min@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"True -> "/utf8, (Min_failure(Min@2))/binary>>
),
_pipe@14 = oaspec@internal@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<"}"/utf8>>
);
{none, {some, Max@2}} ->
_pipe@15 = Sb@1,
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<<<"case count > "/utf8,
(erlang:integer_to_binary(Max@2))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"True -> "/utf8, (Max_failure(Max@2))/binary>>
),
_pipe@18 = oaspec@internal@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@18,
1,
<<"}"/utf8>>
);
{none, none} ->
Sb@1
end,
_pipe@19 = Sb@2,
_pipe@20 = oaspec@internal@util@string_extra:line(
_pipe@19,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1480).
?DOC(false).
-spec validation_failure_dynamic(binary(), binary(), binary()) -> binary().
validation_failure_dynamic(Field, Code, Message_expr) ->
<<<<<<<<<<<<"Error(ValidationFailure(field: "/utf8,
(gleam_string_literal(Field))/binary>>/binary,
", code: "/utf8>>/binary,
(gleam_string_literal(Code))/binary>>/binary,
", message: "/utf8>>/binary,
Message_expr/binary>>/binary,
"))"/utf8>>.
-file("src/oaspec/internal/codegen/guards.gleam", 689).
?DOC(false).
-spec generate_string_pattern_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(binary())
) -> gleam@string_tree:string_tree().
generate_string_pattern_guard(Sb, Schema_name, Prop_name, Pattern) ->
case Pattern of
none ->
Sb;
{some, Pattern@1} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"pattern"/utf8>>
),
Pattern_literal = gleam_string_literal(Pattern@1),
Invalid_pattern_prefix = gleam_string_literal(
<<<<"invalid pattern: "/utf8, Pattern@1/binary>>/binary,
": "/utf8>>
),
Mismatch_failure = validation_failure_literal(
Prop_name,
<<"pattern"/utf8>>,
<<"must match pattern: "/utf8, Pattern@1/binary>>
),
Invalid_pattern_failure = validation_failure_dynamic(
Prop_name,
<<"invalidPattern"/utf8>>,
<<Invalid_pattern_prefix/binary, " <> error"/utf8>>
),
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<"/// Validate string pattern for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: String) -> Result(String, ValidationFailure) {"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<<<"case regexp.from_string("/utf8, Pattern_literal/binary>>/binary,
") {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
2,
<<"Ok(re) -> case regexp.check(re, value) {"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
3,
<<"True -> Ok(value)"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
3,
<<"False -> "/utf8, Mismatch_failure/binary>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
2,
<<"}"/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:indent(
_pipe@7,
2,
<<"Error(regexp.CompileError(error:, ..)) -> "/utf8,
Invalid_pattern_failure/binary>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
1,
<<"}"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:line(
_pipe@9,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@10)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 611).
?DOC(false).
-spec generate_field_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_field_guard(Sb, Schema_name, Prop_name, Prop_ref, Ctx) ->
Resolved = case Prop_ref of
{inline, Schema} ->
{ok, Schema};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Prop_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
case Resolved of
{ok, {string_schema, _, _, _, Min_length, Max_length, Pattern}} ->
Sb@1 = generate_string_guard(
Sb,
Schema_name,
Prop_name,
Min_length,
Max_length
),
generate_string_pattern_guard(Sb@1, Schema_name, Prop_name, Pattern);
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Sb@2 = generate_integer_guard(
Sb,
Schema_name,
Prop_name,
Minimum,
Maximum
),
Sb@3 = generate_integer_exclusive_guard(
Sb@2,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
),
generate_integer_multiple_of_guard(
Sb@3,
Schema_name,
Prop_name,
Multiple_of
);
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Sb@4 = generate_float_guard(
Sb,
Schema_name,
Prop_name,
Minimum@1,
Maximum@1
),
Sb@5 = generate_float_exclusive_guard(
Sb@4,
Schema_name,
Prop_name,
Exclusive_minimum@1,
Exclusive_maximum@1
),
generate_float_multiple_of_guard(
Sb@5,
Schema_name,
Prop_name,
Multiple_of@1
);
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Sb@6 = generate_list_guard(
Sb,
Schema_name,
Prop_name,
Min_items,
Max_items
),
generate_unique_items_guard(
Sb@6,
Schema_name,
Prop_name,
Unique_items
);
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/guards.gleam", 527).
?DOC(false).
-spec generate_guards_for_schema_object(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@schema:schema_object(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_guards_for_schema_object(Sb, Name, Schema, Ctx) ->
case Schema of
{object_schema, _, Properties, _, _, Min_properties, Max_properties} ->
Sb@1 = generate_properties_count_guard(
Sb,
Name,
<<""/utf8>>,
Min_properties,
Max_properties
),
Props = oaspec@internal@codegen@ir_build:sorted_entries(Properties),
gleam@list:fold(
Props,
Sb@1,
fun(Sb@2, Entry) ->
{Prop_name, Prop_ref} = Entry,
generate_field_guard(Sb@2, Name, Prop_name, Prop_ref, Ctx)
end
);
{all_of_schema, _, Schemas} ->
Props@1 = oaspec@internal@codegen@ir_build:sorted_entries(
erlang:element(
2,
oaspec@internal@codegen@allof_merge:merge_allof_schemas(
Schemas,
Ctx
)
)
),
gleam@list:fold(
Props@1,
Sb,
fun(Sb@3, Entry@1) ->
{Prop_name@1, Prop_ref@1} = Entry@1,
generate_field_guard(
Sb@3,
Name,
Prop_name@1,
Prop_ref@1,
Ctx
)
end
);
{string_schema, _, _, _, Min_length, Max_length, Pattern} ->
Sb@4 = generate_string_guard(
Sb,
Name,
<<""/utf8>>,
Min_length,
Max_length
),
generate_string_pattern_guard(Sb@4, Name, <<""/utf8>>, Pattern);
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of} ->
Sb@5 = generate_integer_guard(
Sb,
Name,
<<""/utf8>>,
Minimum,
Maximum
),
Sb@6 = generate_integer_exclusive_guard(
Sb@5,
Name,
<<""/utf8>>,
Exclusive_minimum,
Exclusive_maximum
),
generate_integer_multiple_of_guard(
Sb@6,
Name,
<<""/utf8>>,
Multiple_of
);
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1} ->
Sb@7 = generate_float_guard(
Sb,
Name,
<<""/utf8>>,
Minimum@1,
Maximum@1
),
Sb@8 = generate_float_exclusive_guard(
Sb@7,
Name,
<<""/utf8>>,
Exclusive_minimum@1,
Exclusive_maximum@1
),
generate_float_multiple_of_guard(
Sb@8,
Name,
<<""/utf8>>,
Multiple_of@1
);
{array_schema, _, _, Min_items, Max_items, Unique_items} ->
Sb@9 = generate_list_guard(
Sb,
Name,
<<""/utf8>>,
Min_items,
Max_items
),
generate_unique_items_guard(Sb@9, Name, <<""/utf8>>, Unique_items);
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/guards.gleam", 507).
?DOC(false).
-spec generate_guards_for_schema(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_guards_for_schema(Sb, Name, Schema_ref, Ctx) ->
case Schema_ref of
{inline, Schema} ->
generate_guards_for_schema_object(Sb, Name, Schema, Ctx);
{reference, _, Name@1} ->
Resolved_name = Name@1,
case oaspec@internal@openapi@resolver:resolve_schema_ref(
Schema_ref,
oaspec@internal@codegen@context:spec(Ctx)
) of
{ok, Schema@1} ->
generate_guards_for_schema_object(
Sb,
Resolved_name,
Schema@1,
Ctx
);
_ ->
Sb
end
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1562).
?DOC(false).
-spec composite_validator_type(
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> binary().
composite_validator_type(Name, Schema_ref, Ctx) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Schema_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
case Schema of
{ok, {object_schema, _, _, _, _, _, _}} ->
<<"types."/utf8,
(oaspec@internal@util@naming:schema_to_type_name(Name))/binary>>;
{ok, {all_of_schema, _, _}} ->
<<"types."/utf8,
(oaspec@internal@util@naming:schema_to_type_name(Name))/binary>>;
{ok, S@1} ->
oaspec@internal@codegen@types:schema_to_gleam_type(S@1, Ctx);
_ ->
<<"types."/utf8,
(oaspec@internal@util@naming:schema_to_type_name(Name))/binary>>
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1721).
?DOC(false).
-spec collect_field_guard_calls(
binary(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
boolean(),
oaspec@internal@codegen@context:context()
) -> list({binary(), binary(), boolean()}).
collect_field_guard_calls(Schema_name, Prop_name, Prop_ref, Is_required, Ctx) ->
Resolved = case Prop_ref of
{inline, Schema} ->
{ok, Schema};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Prop_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
Accessor = <<"value."/utf8,
(oaspec@internal@util@naming:to_snake_case(Prop_name))/binary>>,
case Resolved of
{ok, {string_schema, _, _, _, Min_length, Max_length, Pattern}} ->
Calls = case {Min_length, Max_length} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Accessor,
Is_required}]
end,
case Pattern of
none ->
Calls;
{some, _} ->
lists:append(
Calls,
[{guard_function_name(
Schema_name,
Prop_name,
<<"pattern"/utf8>>
),
Accessor,
Is_required}]
)
end;
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Calls@1 = case {Minimum, Maximum} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Accessor,
Is_required}]
end,
Calls@2 = case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Calls@1;
{_, _} ->
lists:append(
Calls@1,
[{guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Accessor,
Is_required}]
)
end,
case Multiple_of of
none ->
Calls@2;
{some, _} ->
lists:append(
Calls@2,
[{guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Accessor,
Is_required}]
)
end;
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Calls@3 = case {Minimum@1, Maximum@1} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Accessor,
Is_required}]
end,
Calls@4 = case {Exclusive_minimum@1, Exclusive_maximum@1} of
{none, none} ->
Calls@3;
{_, _} ->
lists:append(
Calls@3,
[{guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Accessor,
Is_required}]
)
end,
case Multiple_of@1 of
none ->
Calls@4;
{some, _} ->
lists:append(
Calls@4,
[{guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Accessor,
Is_required}]
)
end;
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Length_calls = case {Min_items, Max_items} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Accessor,
Is_required}]
end,
Unique_calls = case Unique_items of
true ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"unique"/utf8>>
),
Accessor,
Is_required}];
false ->
[]
end,
lists:append(Length_calls, Unique_calls);
_ ->
[]
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1587).
?DOC(false).
-spec collect_guard_calls(
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> list({binary(), binary(), boolean()}).
collect_guard_calls(Name, Schema_ref, Ctx) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Schema_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
case Schema of
{ok,
{object_schema,
_,
Properties,
Required,
_,
Min_properties,
Max_properties}} ->
Prop_calls = begin
_pipe = oaspec@internal@codegen@ir_build:sorted_entries(
Properties
),
gleam@list:flat_map(
_pipe,
fun(Entry) ->
{Prop_name, Prop_ref} = Entry,
Is_required = gleam@list:contains(Required, Prop_name),
collect_field_guard_calls(
Name,
Prop_name,
Prop_ref,
Is_required,
Ctx
)
end
)
end,
Size_calls = case {Min_properties, Max_properties} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Name,
<<""/utf8>>,
<<"properties"/utf8>>
),
<<"value"/utf8>>,
true}]
end,
lists:append(Prop_calls, Size_calls);
{ok, {all_of_schema, _, Schemas}} ->
Merged = oaspec@internal@codegen@allof_merge:merge_allof_schemas(
Schemas,
Ctx
),
_pipe@1 = oaspec@internal@codegen@ir_build:sorted_entries(
erlang:element(2, Merged)
),
gleam@list:flat_map(
_pipe@1,
fun(Entry@1) ->
{Prop_name@1, Prop_ref@1} = Entry@1,
Is_required@1 = gleam@list:contains(
erlang:element(3, Merged),
Prop_name@1
),
collect_field_guard_calls(
Name,
Prop_name@1,
Prop_ref@1,
Is_required@1,
Ctx
)
end
);
{ok, {string_schema, _, _, _, Min_length, Max_length, Pattern}} ->
Calls = case {Min_length, Max_length} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"length"/utf8>>),
<<"value"/utf8>>,
true}]
end,
case Pattern of
none ->
Calls;
{some, _} ->
lists:append(
Calls,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"pattern"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end;
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Calls@1 = case {Minimum, Maximum} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"range"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Calls@2 = case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Calls@1;
{_, _} ->
lists:append(
Calls@1,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"exclusive_range"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end,
case Multiple_of of
none ->
Calls@2;
{some, _} ->
lists:append(
Calls@2,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"multiple_of"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end;
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Calls@3 = case {Minimum@1, Maximum@1} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"range"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Calls@4 = case {Exclusive_minimum@1, Exclusive_maximum@1} of
{none, none} ->
Calls@3;
{_, _} ->
lists:append(
Calls@3,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"exclusive_range"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end,
case Multiple_of@1 of
none ->
Calls@4;
{some, _} ->
lists:append(
Calls@4,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"multiple_of"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end;
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Length_calls = case {Min_items, Max_items} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"length"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Unique_calls = case Unique_items of
true ->
[{guard_function_name(Name, <<""/utf8>>, <<"unique"/utf8>>),
<<"value"/utf8>>,
true}];
false ->
[]
end,
lists:append(Length_calls, Unique_calls);
_ ->
[]
end.
-file("src/oaspec/internal/codegen/guards.gleam", 28).
?DOC(false).
-spec schema_has_validator(binary(), oaspec@internal@codegen@context:context()) -> boolean().
schema_has_validator(Name, Ctx) ->
case erlang:element(5, oaspec@internal@codegen@context:spec(Ctx)) of
{some, Components} ->
case gleam_stdlib:map_get(erlang:element(2, Components), Name) of
{ok, Schema_ref} ->
not oaspec@internal@codegen@ir_build:is_internal_schema(
Schema_ref
)
andalso not gleam@list:is_empty(
collect_guard_calls(Name, Schema_ref, Ctx)
);
{error, _} ->
false
end;
none ->
false
end.
-file("src/oaspec/internal/codegen/guards.gleam", 1497).
?DOC(false).
-spec generate_composite_validator(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_composite_validator(Sb, Name, Schema_ref, Ctx) ->
Guard_calls = collect_guard_calls(Name, Schema_ref, Ctx),
case gleam@list:is_empty(Guard_calls) of
true ->
Sb;
false ->
Fn_name = <<"validate_"/utf8,
(oaspec@internal@util@naming:to_snake_case(Name))/binary>>,
Type_name = oaspec@internal@util@naming:schema_to_type_name(Name),
Gleam_type = composite_validator_type(Name, Schema_ref, Ctx),
Sb@1 = begin
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:doc_comment(
_pipe,
<<<<"Validate all constraints for "/utf8, Type_name/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:doc_comment(
_pipe@1,
<<"Auto-calls all field validators and collects failures."/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:line(
_pipe@2,
<<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: "/utf8>>/binary,
Gleam_type/binary>>/binary,
") -> Result("/utf8>>/binary,
Gleam_type/binary>>/binary,
", List(ValidationFailure)) {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<"let errors = []"/utf8>>
)
end,
Sb@3 = gleam@list:fold(
Guard_calls,
Sb@1,
fun(Sb@2, Call) ->
{Guard_fn, Accessor, Is_required} = Call,
case Is_required of
true ->
_pipe@4 = Sb@2,
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
1,
<<<<<<<<"let errors = case "/utf8,
Guard_fn/binary>>/binary,
"("/utf8>>/binary,
Accessor/binary>>/binary,
") {"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
2,
<<"Ok(_) -> errors"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
2,
<<"Error(failure) -> [failure, ..errors]"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@7,
1,
<<"}"/utf8>>
);
false ->
_pipe@8 = Sb@2,
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
1,
<<<<"let errors = case "/utf8, Accessor/binary>>/binary,
" {"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
2,
<<<<"option.Some(v) -> case "/utf8,
Guard_fn/binary>>/binary,
"(v) {"/utf8>>
),
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
3,
<<"Ok(_) -> errors"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:indent(
_pipe@11,
3,
<<"Error(failure) -> [failure, ..errors]"/utf8>>
),
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<"}"/utf8>>
),
_pipe@14 = oaspec@internal@util@string_extra:indent(
_pipe@13,
2,
<<"option.None -> errors"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
<<"}"/utf8>>
)
end
end
),
_pipe@15 = Sb@3,
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<"case errors {"/utf8>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"[] -> Ok(value)"/utf8>>
),
_pipe@18 = oaspec@internal@util@string_extra:indent(
_pipe@17,
2,
<<"_ -> Error(errors)"/utf8>>
),
_pipe@19 = oaspec@internal@util@string_extra:indent(
_pipe@18,
1,
<<"}"/utf8>>
),
_pipe@20 = oaspec@internal@util@string_extra:line(
_pipe@19,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 448).
?DOC(false).
-spec collect_schema_constraint_types_inner(
constraint_types(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context(),
gleam@set:set(binary())
) -> constraint_types().
collect_schema_constraint_types_inner(Acc, Schema_ref, Ctx, Seen) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Schema_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
case Schema of
{ok, {string_schema, _, _, _, Min_length, Max_length, Pattern}} ->
Acc@1 = case {Min_length, Max_length} of
{none, none} ->
Acc;
{_, _} ->
{constraint_types,
true,
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)}
end,
case Pattern of
{some, _} ->
{constraint_types,
erlang:element(2, Acc@1),
true,
erlang:element(4, Acc@1),
erlang:element(5, Acc@1),
erlang:element(6, Acc@1),
erlang:element(7, Acc@1),
erlang:element(8, Acc@1)};
none ->
Acc@1
end;
{ok, {integer_schema, _, _, {some, _}, _, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {integer_schema, _, _, _, {some, _}, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {integer_schema, _, _, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {integer_schema, _, _, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {integer_schema, _, _, _, _, _, _, {some, _}}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {number_schema, _, _, {some, _}, _, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {number_schema, _, _, _, {some, _}, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {number_schema, _, _, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {number_schema, _, _, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {number_schema, _, _, _, _, _, _, {some, _}}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
true,
erlang:element(8, Acc)};
{ok, {array_schema, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
true,
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {array_schema, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
true,
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok, {array_schema, _, _, _, _, true}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
true,
erlang:element(7, Acc),
erlang:element(8, Acc)};
{ok,
{object_schema, _, Properties, _, _, Min_properties, Max_properties}} ->
Acc@2 = case {Min_properties, Max_properties} of
{none, none} ->
Acc;
{_, _} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc),
true}
end,
_pipe = maps:to_list(Properties),
gleam@list:fold(
_pipe,
Acc@2,
fun(A, Prop) ->
{_, Prop_ref} = Prop,
collect_schema_constraint_types(A, Prop_ref, Ctx, Seen)
end
);
{ok, {all_of_schema, _, Schemas}} ->
gleam@list:fold(
Schemas,
Acc,
fun(A@1, S@1) ->
collect_schema_constraint_types(A@1, S@1, Ctx, Seen)
end
);
_ ->
Acc
end.
-file("src/oaspec/internal/codegen/guards.gleam", 425).
?DOC(false).
-spec collect_schema_constraint_types(
constraint_types(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context(),
gleam@set:set(binary())
) -> constraint_types().
collect_schema_constraint_types(Acc, Schema_ref, Ctx, Seen) ->
case Schema_ref of
{reference, _, Name} ->
case gleam@set:contains(Seen, Name) of
true ->
Acc;
false ->
collect_schema_constraint_types_inner(
Acc,
Schema_ref,
Ctx,
gleam@set:insert(Seen, Name)
)
end;
_ ->
collect_schema_constraint_types_inner(Acc, Schema_ref, Ctx, Seen)
end.
-file("src/oaspec/internal/codegen/guards.gleam", 409).
?DOC(false).
-spec collect_constraint_types(
list({binary(), oaspec@internal@openapi@schema:schema_ref()}),
oaspec@internal@codegen@context:context()
) -> constraint_types().
collect_constraint_types(Schemas, Ctx) ->
gleam@list:fold(
Schemas,
{constraint_types, false, false, false, false, false, false, false},
fun(Acc, Entry) ->
{_, Schema_ref} = Entry,
collect_schema_constraint_types(
Acc,
Schema_ref,
Ctx,
gleam@set:new()
)
end
).
-file("src/oaspec/internal/codegen/guards.gleam", 59).
?DOC(false).
-spec generate_guards(oaspec@internal@codegen@context:context()) -> binary().
generate_guards(Ctx) ->
Schemas = case erlang:element(5, oaspec@internal@codegen@context:spec(Ctx)) of
{some, Components} ->
_pipe = gleam@list:sort(
maps:to_list(erlang:element(2, Components)),
fun(A, B) ->
gleam@string:compare(
erlang:element(1, A),
erlang:element(1, B)
)
end
),
gleam@list:filter(
_pipe,
fun(Entry) ->
not oaspec@internal@codegen@ir_build:is_internal_schema(
erlang:element(2, Entry)
)
end
);
none ->
[]
end,
Constraint_types = collect_constraint_types(Schemas, Ctx),
Imports = [<<"gleam/json"/utf8>>],
Imports@1 = case erlang:element(2, Constraint_types) of
true ->
[<<"gleam/string"/utf8>> | Imports];
false ->
Imports
end,
Imports@2 = case erlang:element(3, Constraint_types) of
true ->
[<<"gleam/regexp"/utf8>> | Imports@1];
false ->
Imports@1
end,
Imports@3 = case erlang:element(6, Constraint_types) of
true ->
[<<"gleam/list"/utf8>> | Imports@2];
false ->
Imports@2
end,
Imports@4 = case erlang:element(8, Constraint_types) of
true ->
[<<"gleam/dict.{type Dict}"/utf8>> | Imports@3];
false ->
Imports@3
end,
Imports@5 = case erlang:element(7, Constraint_types) of
true ->
[<<"gleam/int"/utf8>>, <<"gleam/float"/utf8>> | Imports@4];
false ->
Imports@4
end,
Needs_types = gleam@list:any(
Schemas,
fun(Entry@1) ->
{Name, Schema_ref} = Entry@1,
Guard_calls = collect_guard_calls(Name, Schema_ref, Ctx),
case gleam@list:is_empty(Guard_calls) of
true ->
false;
false ->
Resolved = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@internal@openapi@resolver:resolve_schema_ref(
Schema_ref,
oaspec@internal@codegen@context:spec(Ctx)
)
end,
case Resolved of
{ok, {object_schema, _, _, _, _, _, _}} ->
true;
{ok, {all_of_schema, _, _}} ->
true;
_ ->
false
end
end
end
),
Imports@6 = case Needs_types of
true ->
[<<(oaspec@config:package(
oaspec@internal@codegen@context:config(Ctx)
))/binary,
"/types"/utf8>> |
Imports@5];
false ->
Imports@5
end,
Needs_option = gleam@list:any(
Schemas,
fun(Entry@2) ->
{Name@1, Schema_ref@1} = Entry@2,
Guard_calls@1 = collect_guard_calls(Name@1, Schema_ref@1, Ctx),
gleam@list:any(
Guard_calls@1,
fun(Call) ->
{_, _, Is_required} = Call,
not Is_required
end
)
end
),
Imports@7 = case Needs_option of
true ->
[<<"gleam/option"/utf8>> | Imports@6];
false ->
Imports@6
end,
Sb = begin
_pipe@1 = oaspec@internal@util@string_extra:file_header(
<<"0.33.0"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:imports(_pipe@1, Imports@7),
emit_validation_failure_type(_pipe@2)
end,
Sb@2 = gleam@list:fold(
Schemas,
Sb,
fun(Sb@1, Entry@3) ->
{Name@2, Schema_ref@2} = Entry@3,
generate_guards_for_schema(Sb@1, Name@2, Schema_ref@2, Ctx)
end
),
Sb@4 = gleam@list:fold(
Schemas,
Sb@2,
fun(Sb@3, Entry@4) ->
{Name@3, Schema_ref@3} = Entry@4,
generate_composite_validator(Sb@3, Name@3, Schema_ref@3, Ctx)
end
),
_pipe@3 = oaspec@internal@util@string_extra:to_string(Sb@4),
dedupe_field_validator_definitions(_pipe@3).
-file("src/oaspec/internal/codegen/guards.gleam", 43).
?DOC(false).
-spec generate(oaspec@internal@codegen@context:context()) -> list(oaspec@internal@codegen@context:generated_file()).
generate(Ctx) ->
Content = generate_guards(Ctx),
case gleam_stdlib:contains_string(Content, <<"pub fn validate_"/utf8>>) of
true ->
[{generated_file,
<<"guards.gleam"/utf8>>,
Content,
shared_target,
overwrite}];
false ->
[]
end.