Skip to main content

src/gdav@internal@xml.erl

-module(gdav@internal@xml).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gdav/internal/xml.gleam").
-export([find_text/3, parse_sync_report/1, parse_multistatus/1, parse_propfind/1, parse_single_value/2]).
-export_type([property/0, dav_response/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 property() :: {text_prop, xmlm:name(), binary()} |
    {href_prop, xmlm:name(), binary()}.

-type dav_response() :: {dav_response, binary(), integer(), list(property())}.

-file("src/gdav/internal/xml.gleam", 69).
?DOC(false).
-spec find_text(list(property()), binary(), binary()) -> {ok, binary()} |
    {error, nil}.
find_text(Props, Ns, Local) ->
    gleam@list:find_map(Props, fun(P) -> case P of
                {text_prop, {name, Uri, Loc}, V} when (Uri =:= Ns) andalso (Loc =:= Local) ->
                    {ok, V};

                _ ->
                    {error, nil}
            end end).

-file("src/gdav/internal/xml.gleam", 275).
?DOC(false).
-spec do_skip_element(xmlm:input(), integer()) -> {ok, {nil, xmlm:input()}} |
    {error, xmlm:input_error()}.
do_skip_element(Input, Depth) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {element_start, _} ->
                    do_skip_element(Input@1, Depth + 1);

                element_end when Depth =:= 0 ->
                    {ok, {nil, Input@1}};

                element_end ->
                    do_skip_element(Input@1, Depth - 1);

                _ ->
                    do_skip_element(Input@1, Depth)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 269).
?DOC(false).
-spec skip_element(xmlm:input()) -> {ok, {nil, xmlm:input()}} |
    {error, xmlm:input_error()}.
skip_element(Input) ->
    do_skip_element(Input, 0).

-file("src/gdav/internal/xml.gleam", 255).
?DOC(false).
-spec skip_remaining_children(xmlm:input()) -> {ok, {nil, xmlm:input()}} |
    {error, xmlm:input_error()}.
skip_remaining_children(Input) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                element_end ->
                    {ok, {nil, Input@1}};

                {element_start, _} ->
                    gleam@result:'try'(
                        skip_element(Input@1),
                        fun(_use0@1) ->
                            {_, Input@2} = _use0@1,
                            skip_remaining_children(Input@2)
                        end
                    );

                {data, _} ->
                    skip_remaining_children(Input@1);

                {dtd, _} ->
                    skip_remaining_children(Input@1)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 306).
?DOC(false).
-spec read_text_tail(xmlm:input()) -> {ok, {binary(), xmlm:input()}} |
    {error, xmlm:input_error()}.
read_text_tail(Input) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {data, Text} ->
                    gleam@result:'try'(
                        skip_remaining_children(Input@1),
                        fun(_use0@1) ->
                            {_, Input@2} = _use0@1,
                            {ok, {Text, Input@2}}
                        end
                    );

                element_end ->
                    {ok, {<<""/utf8>>, Input@1}};

                {element_start, _} ->
                    gleam@result:'try'(
                        skip_element(Input@1),
                        fun(_use0@2) ->
                            {_, Input@3} = _use0@2,
                            read_text_tail(Input@3)
                        end
                    );

                {dtd, _} ->
                    read_text_tail(Input@1)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 288).
?DOC(false).
-spec read_text(xmlm:input()) -> {ok, {binary(), xmlm:input()}} |
    {error, xmlm:input_error()}.
read_text(Input) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {data, Text} ->
                    gleam@result:'try'(
                        skip_remaining_children(Input@1),
                        fun(_use0@1) ->
                            {_, Input@2} = _use0@1,
                            {ok, {Text, Input@2}}
                        end
                    );

                element_end ->
                    {ok, {<<""/utf8>>, Input@1}};

                {element_start, _} ->
                    gleam@result:'try'(
                        skip_element(Input@1),
                        fun(_use0@2) ->
                            {_, Input@3} = _use0@2,
                            read_text_tail(Input@3)
                        end
                    );

                {dtd, _} ->
                    read_text(Input@1)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 324).
?DOC(false).
-spec parse_status_code(binary()) -> integer().
parse_status_code(Status) ->
    case gleam@string:split(Status, <<" "/utf8>>) of
        [_, Code | _] ->
            _pipe = gleam_stdlib:parse_int(Code),
            gleam@result:unwrap(_pipe, 0);

        _ ->
            0
    end.

-file("src/gdav/internal/xml.gleam", 222).
?DOC(false).
-spec parse_one_prop(xmlm:input(), xmlm:name()) -> {ok,
        {property(), xmlm:input()}} |
    {error, xmlm:input_error()}.
parse_one_prop(Input, Name) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {data, Text} ->
                    case gleam@string:trim(Text) of
                        <<""/utf8>> ->
                            parse_one_prop(Input@1, Name);

                        _ ->
                            gleam@result:'try'(
                                skip_remaining_children(Input@1),
                                fun(_use0@1) ->
                                    {_, Input@2} = _use0@1,
                                    {ok, {{text_prop, Name, Text}, Input@2}}
                                end
                            )
                    end;

                element_end ->
                    {ok, {{text_prop, Name, <<""/utf8>>}, Input@1}};

                {element_start, Child_tag} ->
                    case erlang:element(2, Child_tag) of
                        {name, Uri, <<"href"/utf8>>} when Uri =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                read_text(Input@1),
                                fun(_use0@2) ->
                                    {Href_text, Input@3} = _use0@2,
                                    gleam@result:'try'(
                                        skip_remaining_children(Input@3),
                                        fun(_use0@3) ->
                                            {_, Input@4} = _use0@3,
                                            {ok,
                                                {{href_prop, Name, Href_text},
                                                    Input@4}}
                                        end
                                    )
                                end
                            );

                        _ ->
                            gleam@result:'try'(
                                skip_element(Input@1),
                                fun(_use0@4) ->
                                    {_, Input@5} = _use0@4,
                                    parse_one_prop(Input@5, Name)
                                end
                            )
                    end;

                {dtd, _} ->
                    parse_one_prop(Input@1, Name)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 207).
?DOC(false).
-spec parse_props(xmlm:input(), list(property())) -> {ok,
        {list(property()), xmlm:input()}} |
    {error, xmlm:input_error()}.
parse_props(Input, Acc) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {element_start, Tag} ->
                    gleam@result:'try'(
                        parse_one_prop(Input@1, erlang:element(2, Tag)),
                        fun(_use0@1) ->
                            {Prop, Input@2} = _use0@1,
                            parse_props(Input@2, [Prop | Acc])
                        end
                    );

                element_end ->
                    {ok, {lists:reverse(Acc), Input@1}};

                {data, _} ->
                    parse_props(Input@1, Acc);

                {dtd, _} ->
                    parse_props(Input@1, Acc)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 179).
?DOC(false).
-spec do_parse_propstat(xmlm:input(), list(property()), integer()) -> {ok,
        {list(property()), integer(), xmlm:input()}} |
    {error, xmlm:input_error()}.
do_parse_propstat(Input, Props, Status_code) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {element_start, Tag} ->
                    case erlang:element(2, Tag) of
                        {name, Uri, <<"prop"/utf8>>} when Uri =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                parse_props(Input@1, []),
                                fun(_use0@1) ->
                                    {New_props, Input@2} = _use0@1,
                                    do_parse_propstat(
                                        Input@2,
                                        lists:append(Props, New_props),
                                        Status_code
                                    )
                                end
                            );

                        {name, Uri@1, <<"status"/utf8>>} when Uri@1 =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                read_text(Input@1),
                                fun(_use0@2) ->
                                    {Text, Input@3} = _use0@2,
                                    do_parse_propstat(
                                        Input@3,
                                        Props,
                                        parse_status_code(Text)
                                    )
                                end
                            );

                        _ ->
                            gleam@result:'try'(
                                skip_element(Input@1),
                                fun(_use0@3) ->
                                    {_, Input@4} = _use0@3,
                                    do_parse_propstat(
                                        Input@4,
                                        Props,
                                        Status_code
                                    )
                                end
                            )
                    end;

                element_end ->
                    {ok, {Props, Status_code, Input@1}};

                {data, _} ->
                    do_parse_propstat(Input@1, Props, Status_code);

                {dtd, _} ->
                    do_parse_propstat(Input@1, Props, Status_code)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 173).
?DOC(false).
-spec parse_propstat(xmlm:input()) -> {ok,
        {list(property()), integer(), xmlm:input()}} |
    {error, xmlm:input_error()}.
parse_propstat(Input) ->
    do_parse_propstat(Input, [], 0).

-file("src/gdav/internal/xml.gleam", 127).
?DOC(false).
-spec do_parse_one_response(xmlm:input(), binary(), integer(), list(property())) -> {ok,
        {dav_response(), xmlm:input()}} |
    {error, xmlm:input_error()}.
do_parse_one_response(Input, Href, Status_code, Props) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {element_start, Tag} ->
                    case erlang:element(2, Tag) of
                        {name, Uri, <<"href"/utf8>>} when Uri =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                read_text(Input@1),
                                fun(_use0@1) ->
                                    {Text, Input@2} = _use0@1,
                                    do_parse_one_response(
                                        Input@2,
                                        Text,
                                        Status_code,
                                        Props
                                    )
                                end
                            );

                        {name, Uri@1, <<"propstat"/utf8>>} when Uri@1 =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                parse_propstat(Input@1),
                                fun(_use0@2) ->
                                    {New_props, Pstat_code, Input@3} = _use0@2,
                                    Props@1 = case (Pstat_code >= 200) andalso (Pstat_code
                                    < 300) of
                                        true ->
                                            lists:append(Props, New_props);

                                        false ->
                                            Props
                                    end,
                                    Status_code@1 = case Status_code =:= 0 of
                                        true ->
                                            Pstat_code;

                                        false ->
                                            Status_code
                                    end,
                                    do_parse_one_response(
                                        Input@3,
                                        Href,
                                        Status_code@1,
                                        Props@1
                                    )
                                end
                            );

                        {name, Uri@2, <<"status"/utf8>>} when Uri@2 =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                read_text(Input@1),
                                fun(_use0@3) ->
                                    {Text@1, Input@4} = _use0@3,
                                    Code = parse_status_code(Text@1),
                                    do_parse_one_response(
                                        Input@4,
                                        Href,
                                        Code,
                                        Props
                                    )
                                end
                            );

                        _ ->
                            gleam@result:'try'(
                                skip_element(Input@1),
                                fun(_use0@4) ->
                                    {_, Input@5} = _use0@4,
                                    do_parse_one_response(
                                        Input@5,
                                        Href,
                                        Status_code,
                                        Props
                                    )
                                end
                            )
                    end;

                element_end ->
                    {ok, {{dav_response, Href, Status_code, Props}, Input@1}};

                {data, _} ->
                    do_parse_one_response(Input@1, Href, Status_code, Props);

                {dtd, _} ->
                    do_parse_one_response(Input@1, Href, Status_code, Props)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 121).
?DOC(false).
-spec parse_one_response(xmlm:input()) -> {ok, {dav_response(), xmlm:input()}} |
    {error, xmlm:input_error()}.
parse_one_response(Input) ->
    do_parse_one_response(Input, <<""/utf8>>, 0, []).

-file("src/gdav/internal/xml.gleam", 93).
?DOC(false).
-spec collect_responses(xmlm:input(), list(dav_response()), binary()) -> {ok,
        {list(dav_response()), binary()}} |
    {error, xmlm:input_error()}.
collect_responses(Input, Acc, Sync_token) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {element_start, Tag} ->
                    case erlang:element(2, Tag) of
                        {name, Uri, <<"response"/utf8>>} when Uri =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                parse_one_response(Input@1),
                                fun(_use0@1) ->
                                    {Response, Input@2} = _use0@1,
                                    collect_responses(
                                        Input@2,
                                        [Response | Acc],
                                        Sync_token
                                    )
                                end
                            );

                        {name, Uri@1, <<"sync-token"/utf8>>} when Uri@1 =:= <<"DAV:"/utf8>> ->
                            gleam@result:'try'(
                                read_text(Input@1),
                                fun(_use0@2) ->
                                    {Text, Input@3} = _use0@2,
                                    collect_responses(Input@3, Acc, Text)
                                end
                            );

                        _ ->
                            gleam@result:'try'(
                                skip_element(Input@1),
                                fun(_use0@3) ->
                                    {_, Input@4} = _use0@3,
                                    collect_responses(Input@4, Acc, Sync_token)
                                end
                            )
                    end;

                element_end ->
                    {ok, {lists:reverse(Acc), Sync_token}};

                {data, _} ->
                    collect_responses(Input@1, Acc, Sync_token);

                {dtd, _} ->
                    collect_responses(Input@1, Acc, Sync_token)
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 82).
?DOC(false).
-spec do_parse_multistatus(xmlm:input()) -> {ok,
        {list(dav_response()), binary()}} |
    {error, xmlm:input_error()}.
do_parse_multistatus(Input) ->
    gleam@result:'try'(
        xmlm:signal(Input),
        fun(_use0) ->
            {Signal, Input@1} = _use0,
            case Signal of
                {dtd, _} ->
                    do_parse_multistatus(Input@1);

                {data, _} ->
                    do_parse_multistatus(Input@1);

                {element_start, _} ->
                    collect_responses(Input@1, [], <<""/utf8>>);

                element_end ->
                    {ok, {[], <<""/utf8>>}}
            end
        end
    ).

-file("src/gdav/internal/xml.gleam", 40).
?DOC(false).
-spec parse_sync_report(binary()) -> {ok, {list(dav_response()), binary()}} |
    {error, gdav:dav_error()}.
parse_sync_report(Body) ->
    _pipe = xmlm:from_string(Body),
    _pipe@1 = do_parse_multistatus(_pipe),
    gleam@result:map_error(
        _pipe@1,
        fun(E) -> {could_not_parse_xml, xmlm:input_error_to_string(E)} end
    ).

-file("src/gdav/internal/xml.gleam", 25).
?DOC(false).
-spec parse_multistatus(binary()) -> {ok, list(dav_response())} |
    {error, gdav:dav_error()}.
parse_multistatus(Body) ->
    gleam@result:'try'(
        parse_sync_report(Body),
        fun(_use0) ->
            {Responses, _} = _use0,
            {ok, Responses}
        end
    ).

-file("src/gdav/internal/xml.gleam", 32).
?DOC(false).
-spec parse_propfind(binary()) -> {ok, dav_response()} |
    {error, gdav:dav_error()}.
parse_propfind(Body) ->
    gleam@result:'try'(
        parse_multistatus(Body),
        fun(Responses) -> case Responses of
                [R | _] ->
                    {ok, R};

                [] ->
                    {error,
                        {could_not_parse_xml,
                            <<"Empty multistatus response"/utf8>>}}
            end end
    ).

-file("src/gdav/internal/xml.gleam", 50).
?DOC(false).
-spec parse_single_value(binary(), xmlm:name()) -> {ok, binary()} |
    {error, gdav:dav_error()}.
parse_single_value(Body, Container) ->
    gleam@result:'try'(
        parse_propfind(Body),
        fun(Response) ->
            case gleam@list:find_map(
                erlang:element(4, Response),
                fun(P) -> case P of
                        {href_prop, Name, Href} when Name =:= Container ->
                            {ok, Href};

                        _ ->
                            {error, nil}
                    end end
            ) of
                {ok, Href@1} ->
                    {ok, Href@1};

                {error, _} ->
                    {error,
                        {could_not_parse_xml,
                            <<"Property not found: "/utf8,
                                (erlang:element(3, Container))/binary>>}}
            end
        end
    ).