-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()), boolean()} | {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()), boolean()}. -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) -> {t_union, erlang:element(3, Constraints), erlang:element(4, Constraints) =:= {some, true}}. -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", 281). -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", 292). ?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", 299). -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", 306). -spec is_record(flat_def()) -> boolean(). is_record(Def) -> case Def of {flat_record, _, _} -> true; _ -> false end. -file("src/atproto_codegen/lower.gleam", 313). -spec union_of(flat_type()) -> gleam@option:option({list(binary()), boolean()}). union_of(Ft) -> case Ft of {t_union, Refs, Closed} -> {some, {Refs, Closed}}; {t_array, Inner} -> union_of(Inner); _ -> none end. -file("src/atproto_codegen/lower.gleam", 325). ?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, Closed}} -> {ok, {union_unit, Def, Field, Refs, Closed}}; none -> {error, nil} end end ) end, [{def_unit, Def} | Unions] end ).