Current section
Files
Jump to
Current section
Files
src/glerd_json.erl
-module(glerd_json).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([generate/2]).
-spec decode_tuple(
list(glerd@types:field_type(binary())),
gleam@dict:dict(binary(), {any(),
binary(),
list({binary(), glerd@types:field_type(binary())})})
) -> binary().
decode_tuple(Types, Record_info_dict) ->
Arity = begin
_pipe = erlang:length(Types),
gleam@int:to_string(_pipe)
end,
Body = begin
_pipe@1 = Types,
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Typ) -> decode_field_type(Typ, Record_info_dict) end
),
gleam@string:join(_pipe@2, <<","/utf8>>)
end,
<<<<<<<<"dynamic.tuple"/utf8, Arity/binary>>/binary, "("/utf8>>/binary,
Body/binary>>/binary,
")"/utf8>>.
-spec decode_field_type(
glerd@types:field_type(binary()),
gleam@dict:dict(binary(), {any(),
binary(),
list({binary(), glerd@types:field_type(binary())})})
) -> binary().
decode_field_type(Typ, Record_info_dict) ->
case Typ of
is_string ->
<<"dynamic.string"/utf8>>;
is_int ->
<<"dynamic.int"/utf8>>;
is_float ->
<<"dynamic.float"/utf8>>;
is_bool ->
<<"dynamic.bool"/utf8>>;
{is_list, Typ@1} ->
<<<<"dynamic.list("/utf8,
(decode_field_type(Typ@1, Record_info_dict))/binary>>/binary,
")"/utf8>>;
{is_option, Typ@2} ->
<<<<"dynamic.optional("/utf8,
(decode_field_type(Typ@2, Record_info_dict))/binary>>/binary,
")"/utf8>>;
{is_dict, Key_typ, Val_typ} ->
<<<<<<<<"dynamic.dict("/utf8,
(decode_field_type(Key_typ, Record_info_dict))/binary>>/binary,
", "/utf8>>/binary,
(decode_field_type(Val_typ, Record_info_dict))/binary>>/binary,
")"/utf8>>;
{is_tuple2, Typ1, Typ2} ->
decode_tuple([Typ1, Typ2], Record_info_dict);
{is_tuple3, Typ1@1, Typ2@1, Typ3} ->
decode_tuple([Typ1@1, Typ2@1, Typ3], Record_info_dict);
{is_tuple4, Typ1@2, Typ2@2, Typ3@1, Typ4} ->
decode_tuple([Typ1@2, Typ2@2, Typ3@1, Typ4], Record_info_dict);
{is_tuple5, Typ1@3, Typ2@3, Typ3@2, Typ4@1, Typ5} ->
decode_tuple(
[Typ1@3, Typ2@3, Typ3@2, Typ4@1, Typ5],
Record_info_dict
);
{is_tuple6, Typ1@4, Typ2@4, Typ3@3, Typ4@2, Typ5@1, Typ6} ->
decode_tuple(
[Typ1@4, Typ2@4, Typ3@3, Typ4@2, Typ5@1, Typ6],
Record_info_dict
);
{is_record, Record_name} ->
_assert_subject = gleam@dict:get(Record_info_dict, Record_name),
{ok, {_, Module_name, Record_fields}} = case _assert_subject of
{ok, {_, _, _}} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"glerd_json"/utf8>>,
function => <<"decode_field_type"/utf8>>,
line => 154})
end,
Arity = begin
_pipe = erlang:length(Record_fields),
gleam@int:to_string(_pipe)
end,
<<<<<<<<<<<<<<<<"dynamic.decode"/utf8, Arity/binary>>/binary,
"(
"/utf8>>/binary,
Module_name/binary>>/binary,
"."/utf8>>/binary,
Record_name/binary>>/binary,
",
"/utf8>>/binary,
(begin
_pipe@1 = gleam@list:map(
Record_fields,
fun(X) ->
{Fname, Typ@3} = X,
<<<<<<<<"dynamic.field(\""/utf8, Fname/binary>>/binary,
"\", "/utf8>>/binary,
(decode_field_type(
Typ@3,
Record_info_dict
))/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@1, <<",\n"/utf8>>)
end)/binary>>/binary,
"
)"/utf8>>;
X@1 ->
erlang:error(#{gleam_error => panic,
message => (<<"Type decode not supported: "/utf8,
(gleam@string:inspect(X@1))/binary>>),
module => <<"glerd_json"/utf8>>,
function => <<"decode_field_type"/utf8>>,
line => 171})
end.
-spec encode_tuple(
binary(),
list(glerd@types:field_type(JTH)),
gleam@dict:dict(JTH, {any(),
any(),
list({binary(), glerd@types:field_type(JTH)})})
) -> binary().
encode_tuple(Name, Types, Record_info_dict) ->
Tuple_body = begin
_pipe = Types,
_pipe@1 = gleam@list:index_map(
_pipe,
fun(Typ, I) ->
Typ@1 = encode_field_type(
<<"__just_type__"/utf8>>,
Typ,
Record_info_dict
),
<<<<<<<<<<Typ@1/binary, "(x"/utf8>>/binary, Name/binary>>/binary,
"."/utf8>>/binary,
(gleam@int:to_string(I))/binary>>/binary,
"),"/utf8>>
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<"json.preprocessed_array(["/utf8, Tuple_body/binary>>/binary,
"])"/utf8>>.
-spec encode_field_type(
binary(),
glerd@types:field_type(JTH),
gleam@dict:dict(JTH, {any(),
any(),
list({binary(), glerd@types:field_type(JTH)})})
) -> binary().
encode_field_type(Name, Typ, Record_info_dict) ->
case Typ of
is_string when Name =:= <<"__just_type__"/utf8>> ->
<<"json.string"/utf8>>;
is_string ->
<<<<"json.string(x"/utf8, Name/binary>>/binary, ")"/utf8>>;
is_bool when Name =:= <<"__just_type__"/utf8>> ->
<<"json.bool"/utf8>>;
is_bool ->
<<<<"json.bool(x"/utf8, Name/binary>>/binary, ")"/utf8>>;
is_int when Name =:= <<"__just_type__"/utf8>> ->
<<"json.int"/utf8>>;
is_int ->
<<<<"json.int(x"/utf8, Name/binary>>/binary, ")"/utf8>>;
is_float when Name =:= <<"__just_type__"/utf8>> ->
<<<<"json.float(x"/utf8, Name/binary>>/binary, ")"/utf8>>;
is_float ->
<<<<"json.float(x"/utf8, Name/binary>>/binary, ")"/utf8>>;
{is_list, Typ@1} ->
Nested_type = encode_field_type(
<<"__just_type__"/utf8>>,
Typ@1,
Record_info_dict
),
<<<<<<<<"json.array(x"/utf8, Name/binary>>/binary, ", "/utf8>>/binary,
Nested_type/binary>>/binary,
")"/utf8>>;
{is_option, Typ@2} ->
Nested_type@1 = encode_field_type(
<<"__just_type__"/utf8>>,
Typ@2,
Record_info_dict
),
<<<<<<<<"json.nullable(x"/utf8, Name/binary>>/binary, ", "/utf8>>/binary,
Nested_type@1/binary>>/binary,
")"/utf8>>;
{is_tuple2, Typ1, Typ2} ->
encode_tuple(Name, [Typ1, Typ2], Record_info_dict);
{is_tuple3, Typ1@1, Typ2@1, Typ3} ->
encode_tuple(Name, [Typ1@1, Typ2@1, Typ3], Record_info_dict);
{is_tuple4, Typ1@2, Typ2@2, Typ3@1, Typ4} ->
encode_tuple(Name, [Typ1@2, Typ2@2, Typ3@1, Typ4], Record_info_dict);
{is_tuple5, Typ1@3, Typ2@3, Typ3@2, Typ4@1, Typ5} ->
encode_tuple(
Name,
[Typ1@3, Typ2@3, Typ3@2, Typ4@1, Typ5],
Record_info_dict
);
{is_tuple6, Typ1@4, Typ2@4, Typ3@3, Typ4@2, Typ5@1, Typ6} ->
encode_tuple(
Name,
[Typ1@4, Typ2@4, Typ3@3, Typ4@2, Typ5@1, Typ6],
Record_info_dict
);
{is_record, Record_name} ->
_assert_subject = gleam@dict:get(Record_info_dict, Record_name),
{ok, {_, _, Record_fields}} = case _assert_subject of
{ok, {_, _, _}} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"glerd_json"/utf8>>,
function => <<"encode_field_type"/utf8>>,
line => 101})
end,
<<<<"json.object(["/utf8,
(gleam@list:fold(
Record_fields,
<<""/utf8>>,
fun(Acc, Field) ->
{Fname, Typ@3} = Field,
Ftype = encode_field_type(
<<<<Name/binary, "."/utf8>>/binary,
Fname/binary>>,
Typ@3,
Record_info_dict
),
<<<<<<<<<<Acc/binary, "#(\""/utf8>>/binary,
Fname/binary>>/binary,
"\", "/utf8>>/binary,
Ftype/binary>>/binary,
"),"/utf8>>
end
))/binary>>/binary,
"])"/utf8>>;
{is_dict, _, Val_typ} ->
Val_typ@1 = encode_field_type(
<<"__just_type__"/utf8>>,
Val_typ,
Record_info_dict
),
<<<<<<<<"json.object(
x"/utf8, Name/binary>>/binary,
"
|> dict.to_list
|> list.map(fn(x) {
#(x.0,"/utf8>>/binary,
Val_typ@1/binary>>/binary,
"(x.1))
})
)"/utf8>>;
X ->
erlang:error(#{gleam_error => panic,
message => (<<"Type encode not supported: "/utf8,
(gleam@string:inspect(X))/binary>>),
module => <<"glerd_json"/utf8>>,
function => <<"encode_field_type"/utf8>>,
line => 124})
end.
-spec generate(
binary(),
list({binary(),
binary(),
list({binary(), glerd@types:field_type(binary())})})
) -> nil.
generate(Root, Record_info) ->
Imports = begin
_pipe = Record_info,
_pipe@1 = gleam@list:map(
_pipe,
fun(Ri) ->
{_, Module_name, _} = Ri,
<<"import "/utf8, Module_name/binary>>
end
),
_pipe@2 = gleam@list:unique(_pipe@1),
gleam@string:join(_pipe@2, <<"\n"/utf8>>)
end,
Record_info_dict = gleam@list:fold(
Record_info,
gleam@dict:new(),
fun(Acc, Ri@1) ->
{Name, _, _} = Ri@1,
gleam@dict:insert(Acc, Name, Ri@1)
end
),
Gen_content = gleam@list:fold(
Record_info,
<<"// this file was generated via glerd_json
import gleam/json
import gleam/dynamic
import gleam/dict
import gleam/list
"/utf8,
Imports/binary>>,
fun(Acc@1, Rinfo) ->
{Record_name, Module_name@1, _} = Rinfo,
Fn_name_prefix = justin:snake_case(Record_name),
Encoded = encode_field_type(
<<""/utf8>>,
{is_record, Record_name},
Record_info_dict
),
Decoded = decode_field_type(
{is_record, Record_name},
Record_info_dict
),
<<<<<<<<<<<<<<<<<<<<<<<<<<Acc@1/binary, "
pub fn "/utf8>>/binary,
Fn_name_prefix/binary>>/binary,
"_json_encode(x: "/utf8>>/binary,
Module_name@1/binary>>/binary,
"."/utf8>>/binary,
Record_name/binary>>/binary,
") {
"/utf8>>/binary,
Encoded/binary>>/binary,
"
|> json.to_string
}
pub fn "/utf8>>/binary,
Fn_name_prefix/binary>>/binary,
"_json_decode(s: String) {
"/utf8>>/binary,
Decoded/binary>>/binary,
"
|> json.decode(s, _)
}
"/utf8>>
end
),
Gen_file_path = <<<<"./"/utf8, Root/binary>>/binary,
"/glerd_json_gen.gleam"/utf8>>,
_assert_subject = simplifile:write(Gen_file_path, Gen_content),
{ok, _} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"glerd_json"/utf8>>,
function => <<"generate"/utf8>>,
line => 57})
end,
_assert_subject@1 = gleamyshell_ffi:execute(
<<"gleam"/utf8>>,
<<"."/utf8>>,
[<<"format"/utf8>>, Gen_file_path]
),
{ok, _} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"glerd_json"/utf8>>,
function => <<"generate"/utf8>>,
line => 59})
end,
nil.