Current section
Files
Jump to
Current section
Files
src/atproto_codegen@lower.erl
-module(atproto_codegen@lower).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/atproto_codegen/lower.gleam").
-export([lower/1, properties_of/1, method_of/1, is_emittable/1, is_record/1, union_of/1, codec_units/1]).
-export_type([flat_type/0, flat_field/0, flat_def/0, method_kind/0, method_error/0, flat_body/0, flat_body_schema/0, method/0, flat_lexicon/0, codec_unit/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(
" One-way lowering from `atproto_lexicon/ast.LexiconDoc` to the flat view\n"
" plugins consume. `ast` stays the faithful, bidirectional representation;\n"
" this module intentionally drops anything today's plugins do not need\n"
" (method defs, record key strategy, constraint fields, descriptions) while\n"
" keeping a handle on the source doc so a later constraint-aware plugin can\n"
" still reach it. Growing the flat shape (e.g. surfacing a constraint) is\n"
" fine; this module must never grow the ability to go the other way.\n"
"\n"
" A record/object def whose properties use a field type this pipeline\n"
" cannot render becomes `FlatUnsupported` rather than emitted wrong. A\n"
" query/procedure def becomes a `FlatMethod` (consumed by the xrpc-client\n"
" plugin, not the per-unit codec path); any other non-record/object def\n"
" (subscription, token, ...) becomes `FlatIgnored`, since no plugin\n"
" generates code for those yet.\n"
).
-type flat_type() :: t_string |
t_int |
t_bool |
t_cid_link |
t_bytes |
t_blob |
t_unknown |
{t_ref, binary()} |
{t_array, flat_type()} |
{t_union, list(binary())} |
{t_unsupported, binary()}.
-type flat_field() :: {flat_field, binary(), flat_type(), boolean(), boolean()}.
-type flat_def() :: {flat_record, binary(), list(flat_field())} |
{flat_object, binary(), binary(), list(flat_field())} |
{flat_unsupported, binary(), binary(), binary()} |
{flat_method, method()} |
flat_ignored.
-type method_kind() :: method_query | method_procedure.
-type method_error() :: {method_error, binary(), gleam@option:option(binary())}.
-type flat_body() :: {flat_body,
binary(),
gleam@option:option(flat_body_schema())}.
-type flat_body_schema() :: {body_ref, binary()} |
{body_inline, list(flat_field())} |
{body_unsupported, binary()}.
-type method() :: {method,
binary(),
method_kind(),
list(flat_field()),
gleam@option:option(flat_body()),
gleam@option:option(flat_body()),
list(method_error())}.
-type flat_lexicon() :: {flat_lexicon,
binary(),
atproto_lexicon@ast:lexicon_doc(),
list(flat_def())}.
-type codec_unit() :: {def_unit, flat_def()} |
{union_unit, flat_def(), flat_field(), list(binary())}.
-file("src/atproto_codegen/lower.gleam", 202).
-spec lower_errors(list(atproto_lexicon@ast:lexicon_error())) -> list(method_error()).
lower_errors(Errors) ->
gleam@list:map(
Errors,
fun(E) -> {method_error, erlang:element(2, E), erlang:element(3, E)} end
).
-file("src/atproto_codegen/lower.gleam", 240).
-spec unsupported_kind(flat_type()) -> gleam@option:option(binary()).
unsupported_kind(Ft) ->
case Ft of
{t_unsupported, Kind} ->
{some, Kind};
{t_array, Inner} ->
unsupported_kind(Inner);
_ ->
none
end.
-file("src/atproto_codegen/lower.gleam", 227).
-spec first_unsupported(list(flat_field())) -> gleam@option:option(binary()).
first_unsupported(Fields) ->
_pipe = Fields,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(F) -> case unsupported_kind(erlang:element(3, F)) of
{some, Kind} ->
{ok,
<<<<<<<<"field `"/utf8, (erlang:element(2, F))/binary>>/binary,
"` has type `"/utf8>>/binary,
Kind/binary>>/binary,
"`"/utf8>>};
none ->
{error, nil}
end end
),
_pipe@2 = gleam@list:first(_pipe@1),
gleam@option:from_result(_pipe@2).
-file("src/atproto_codegen/lower.gleam", 277).
-spec lower_union(atproto_lexicon@ast:union_constraints()) -> flat_type().
lower_union(Constraints) ->
case erlang:element(4, Constraints) of
{some, true} ->
{t_unsupported, <<"closed union"/utf8>>};
_ ->
{t_union, erlang:element(3, Constraints)}
end.
-file("src/atproto_codegen/lower.gleam", 263).
-spec lower_array_item_type(atproto_lexicon@ast:array_item_type()) -> flat_type().
lower_array_item_type(Item) ->
case Item of
{item_boolean, _} ->
t_bool;
{item_integer, _} ->
t_int;
{item_string, _} ->
t_string;
{item_bytes, _} ->
t_bytes;
{item_cid_link, _} ->
t_cid_link;
{item_blob, _} ->
t_blob;
{item_ref, _, Ref} ->
{t_ref, Ref};
{item_union, Constraints} ->
lower_union(Constraints);
{item_unknown, _} ->
t_unknown
end.
-file("src/atproto_codegen/lower.gleam", 248).
-spec lower_property_type(atproto_lexicon@ast:property_type()) -> flat_type().
lower_property_type(Prop) ->
case Prop of
{prop_boolean, _} ->
t_bool;
{prop_integer, _} ->
t_int;
{prop_string, _} ->
t_string;
{prop_bytes, _} ->
t_bytes;
{prop_cid_link, _} ->
t_cid_link;
{prop_blob, _} ->
t_blob;
{prop_ref, _, Ref} ->
{t_ref, Ref};
{prop_union, Constraints} ->
lower_union(Constraints);
{prop_unknown, _} ->
t_unknown;
{prop_array, Shape} ->
{t_array, lower_array_item_type(erlang:element(3, Shape))}
end.
-file("src/atproto_codegen/lower.gleam", 208).
-spec lower_properties(atproto_lexicon@ast:object_schema()) -> {ok,
list(flat_field())} |
{error, binary()}.
lower_properties(Schema) ->
Fields = gleam@list:map(
erlang:element(5, Schema),
fun(Pair) ->
{Json_name, Prop} = Pair,
{flat_field,
Json_name,
lower_property_type(Prop),
gleam@list:contains(erlang:element(3, Schema), Json_name),
gleam@list:contains(erlang:element(4, Schema), Json_name)}
end
),
case first_unsupported(Fields) of
{some, Reason} ->
{error, Reason};
none ->
{ok, Fields}
end.
-file("src/atproto_codegen/lower.gleam", 189).
-spec lower_body_schema(gleam@option:option(atproto_lexicon@ast:body_schema())) -> gleam@option:option(flat_body_schema()).
lower_body_schema(Schema) ->
case Schema of
none ->
none;
{some, {body_schema_ref, Ref}} ->
{some, {body_ref, Ref}};
{some, {body_schema_object, Obj}} ->
case lower_properties(Obj) of
{ok, Props} ->
{some, {body_inline, Props}};
{error, Reason} ->
{some, {body_unsupported, Reason}}
end;
{some, {body_schema_union, _}} ->
{some, {body_unsupported, <<"union body"/utf8>>}}
end.
-file("src/atproto_codegen/lower.gleam", 181).
-spec lower_body(gleam@option:option(atproto_lexicon@ast:body())) -> gleam@option:option(flat_body()).
lower_body(Body) ->
case Body of
none ->
none;
{some, B} ->
{some,
{flat_body,
erlang:element(3, B),
lower_body_schema(erlang:element(4, B))}}
end.
-file("src/atproto_codegen/lower.gleam", 173).
-spec lower_params_item_type(atproto_lexicon@ast:params_item_type()) -> flat_type().
lower_params_item_type(Item) ->
case Item of
{params_item_boolean, _} ->
t_bool;
{params_item_integer, _} ->
t_int;
{params_item_string, _} ->
t_string
end.
-file("src/atproto_codegen/lower.gleam", 163).
-spec lower_params_property_type(atproto_lexicon@ast:params_property_type()) -> flat_type().
lower_params_property_type(Prop) ->
case Prop of
{params_boolean, _} ->
t_bool;
{params_integer, _} ->
t_int;
{params_string, _} ->
t_string;
{params_unknown, _} ->
{t_unsupported, <<"unknown"/utf8>>};
{params_array, _, Items, _, _} ->
{t_array, lower_params_item_type(Items)}
end.
-file("src/atproto_codegen/lower.gleam", 147).
-spec lower_params(gleam@option:option(atproto_lexicon@ast:params_schema())) -> list(flat_field()).
lower_params(Params) ->
case Params of
none ->
[];
{some, Schema} ->
gleam@list:map(
erlang:element(4, Schema),
fun(Pair) ->
{Json_name, Prop} = Pair,
{flat_field,
Json_name,
lower_params_property_type(Prop),
gleam@list:contains(
erlang:element(3, Schema),
Json_name
),
false}
end
)
end.
-file("src/atproto_codegen/lower.gleam", 113).
-spec lower_def(binary(), binary(), atproto_lexicon@ast:primary_def()) -> flat_def().
lower_def(Nsid, Name, Def) ->
case Def of
{def_record, Record_def} ->
case lower_properties(erlang:element(4, Record_def)) of
{ok, Props} ->
{flat_record, Nsid, Props};
{error, Reason} ->
{flat_unsupported, Nsid, Name, Reason}
end;
{def_object, Schema} ->
case lower_properties(Schema) of
{ok, Props@1} ->
{flat_object, Nsid, Name, Props@1};
{error, Reason@1} ->
{flat_unsupported, Nsid, Name, Reason@1}
end;
{def_query, Q} ->
{flat_method,
{method,
Nsid,
method_query,
lower_params(erlang:element(3, Q)),
none,
lower_body(erlang:element(4, Q)),
lower_errors(erlang:element(5, Q))}};
{def_procedure, P} ->
{flat_method,
{method,
Nsid,
method_procedure,
lower_params(erlang:element(3, P)),
lower_body(erlang:element(4, P)),
lower_body(erlang:element(5, P)),
lower_errors(erlang:element(6, P))}};
_ ->
flat_ignored
end.
-file("src/atproto_codegen/lower.gleam", 108).
-spec lower_doc(atproto_lexicon@ast:lexicon_doc()) -> flat_lexicon().
lower_doc(Doc) ->
Defs = gleam@list:map(
erlang:element(6, Doc),
fun(Pair) ->
lower_def(
erlang:element(3, Doc),
erlang:element(1, Pair),
erlang:element(2, Pair)
)
end
),
{flat_lexicon, erlang:element(3, Doc), Doc, Defs}.
-file("src/atproto_codegen/lower.gleam", 104).
-spec lower(list(atproto_lexicon@ast:lexicon_doc())) -> list(flat_lexicon()).
lower(Docs) ->
gleam@list:map(Docs, fun lower_doc/1).
-file("src/atproto_codegen/lower.gleam", 285).
-spec properties_of(flat_def()) -> list(flat_field()).
properties_of(Def) ->
case Def of
{flat_record, _, Props} ->
Props;
{flat_object, _, _, Props@1} ->
Props@1;
{flat_unsupported, _, _, _} ->
[];
{flat_method, _} ->
[];
flat_ignored ->
[]
end.
-file("src/atproto_codegen/lower.gleam", 296).
?DOC(
" The lowered method for a def, when it is one. Methods are not emittable\n"
" through the per-unit codec path (`is_emittable` is `False` for them); the\n"
" xrpc-client plugin reads them off `lex.defs` via this accessor instead.\n"
).
-spec method_of(flat_def()) -> gleam@option:option(method()).
method_of(Def) ->
case Def of
{flat_method, Method} ->
{some, Method};
_ ->
none
end.
-file("src/atproto_codegen/lower.gleam", 303).
-spec is_emittable(flat_def()) -> boolean().
is_emittable(Def) ->
case Def of
{flat_record, _, _} ->
true;
{flat_object, _, _, _} ->
true;
{flat_unsupported, _, _, _} ->
false;
{flat_method, _} ->
false;
flat_ignored ->
false
end.
-file("src/atproto_codegen/lower.gleam", 310).
-spec is_record(flat_def()) -> boolean().
is_record(Def) ->
case Def of
{flat_record, _, _} ->
true;
_ ->
false
end.
-file("src/atproto_codegen/lower.gleam", 317).
-spec union_of(flat_type()) -> gleam@option:option(list(binary())).
union_of(Ft) ->
case Ft of
{t_union, Refs} ->
{some, Refs};
{t_array, Inner} ->
union_of(Inner);
_ ->
none
end.
-file("src/atproto_codegen/lower.gleam", 329).
?DOC(
" The ordered codec units for one module's emittable defs: each def's own\n"
" unit, immediately followed by one unit per union-typed field on it, in\n"
" field order. Both the `types` and `decode-json` plugins fold over this\n"
" same list so their outputs line up position for position.\n"
).
-spec codec_units(list(flat_def())) -> list(codec_unit()).
codec_units(Defs) ->
_pipe = Defs,
_pipe@1 = gleam@list:filter(_pipe, fun is_emittable/1),
gleam@list:flat_map(
_pipe@1,
fun(Def) ->
Unions = begin
_pipe@2 = properties_of(Def),
gleam@list:filter_map(
_pipe@2,
fun(Field) -> case union_of(erlang:element(3, Field)) of
{some, Refs} ->
{ok, {union_unit, Def, Field, Refs}};
none ->
{error, nil}
end end
)
end,
[{def_unit, Def} | Unions]
end
).