Packages

A pure gleam json decoder, encoder, and json pointer resolver

Current section

Files

Jump to
jackson src jackson@internal@resolver.erl
Raw

src/jackson@internal@resolver.erl

-module(jackson@internal@resolver).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([resolve/2]).
-export_type([ref/0]).
-type ref() :: {root, boolean(), gleam@option:option(ref())} |
{ref, binary(), gleam@option:option(ref())}.
-spec ref_loop(list(binary())) -> gleam@option:option(ref()).
ref_loop(Path_items) ->
case Path_items of
[] ->
none;
[First | Rest] ->
{some, {ref, First, ref_loop(Rest)}}
end.
-spec parse_ref(binary()) -> ref().
parse_ref(Ref) ->
{First, Split} = begin
_pipe = gleam@string:split(Ref, <<"/"/utf8>>),
gleam@list:split(_pipe, 1)
end,
[Fragment_ident] = case First of
[_] -> First;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"parse_ref"/utf8>>,
line => 87})
end,
Fragment_ident_enabled = Fragment_ident =:= <<"#"/utf8>>,
Descaped = begin
_pipe@1 = gleam@list:map(
Split,
fun(_capture) ->
gleam@string:replace(_capture, <<"~1"/utf8>>, <<"/"/utf8>>)
end
),
gleam@list:map(
_pipe@1,
fun(_capture@1) ->
gleam@string:replace(_capture@1, <<"~0"/utf8>>, <<"~"/utf8>>)
end
)
end,
{root, Fragment_ident_enabled, ref_loop(Descaped)}.
-spec resolve_array_ref(list(jackson@internal@json:json()), ref()) -> {ok,
jackson@internal@json:json()} |
{error, nil}.
resolve_array_ref(Entries, Ref) ->
{ref, Value, Next} = case Ref of
{ref, _, _} -> Ref;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"resolve_array_ref"/utf8>>,
line => 33})
end,
_assert_subject = gleam@regex:from_string(<<"^(-|([1-9][0-9]+))$"/utf8>>),
{ok, Re} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"resolve_array_ref"/utf8>>,
line => 34})
end,
Is_valid_array_path = gleam@regex:check(Re, Value),
gleam@bool:guard(
not Is_valid_array_path,
{error, nil},
fun() ->
Indexed_item = case Value of
<<"-"/utf8>> ->
{error, nil};
Idx ->
_assert_subject@1 = gleam@int:parse(Idx),
{ok, Idx@1} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@2,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"resolve_array_ref"/utf8>>,
line => 42})
end,
gleam@list:index_fold(
Entries,
{error, nil},
fun(Found, Val, Index) -> case {Found, Index} of
{_, _} when Index =:= Idx@1 ->
{ok, Val};
{_, _} ->
Found
end end
)
end,
gleam@result:'try'(Indexed_item, fun(Json) -> case Next of
none ->
{ok, Json};
{some, Ref@1} ->
resolve_loop(Json, Ref@1)
end end)
end
).
-spec resolve_loop(jackson@internal@json:json(), ref()) -> {ok,
jackson@internal@json:json()} |
{error, nil}.
resolve_loop(Json, Ref) ->
case Json of
{object, Entries} ->
resolve_object_ref(Entries, Ref);
{array, Entries@1} ->
resolve_array_ref(Entries@1, Ref);
_ ->
{error, nil}
end.
-spec resolve(jackson@internal@json:json(), binary()) -> {ok,
jackson@internal@json:json()} |
{error, nil}.
resolve(Json, Ref) ->
_assert_subject = parse_ref(Ref),
{root, _, Next_ref} = case _assert_subject of
{root, _, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"resolve"/utf8>>,
line => 16})
end,
case Next_ref of
none ->
{ok, Json};
{some, Ref@1} ->
resolve_loop(Json, Ref@1)
end.
-spec resolve_object_ref(list({binary(), jackson@internal@json:json()}), ref()) -> {ok,
jackson@internal@json:json()} |
{error, nil}.
resolve_object_ref(Entries, Ref) ->
{ref, Value, Next} = case Ref of
{ref, _, _} -> Ref;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"jackson/internal/resolver"/utf8>>,
function => <<"resolve_object_ref"/utf8>>,
line => 64})
end,
Search_codepoints = gleam@string:to_utf_codepoints(Value),
Found = gleam@list:find(
Entries,
fun(Entry) ->
Key_codepoints = gleam@string:to_utf_codepoints(
erlang:element(1, Entry)
),
gleam@bool:guard(
Search_codepoints =:= Key_codepoints,
true,
fun() -> false end
)
end
),
gleam@result:'try'(
Found,
fun(_use0) ->
{_, Json} = _use0,
case Next of
none ->
{ok, Json};
{some, Ref@1} ->
resolve_loop(Json, Ref@1)
end
end
).