Skip to main content

src/aws@pagination.erl

-module(aws@pagination).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/pagination.gleam").
-export([fold/3]).

-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(
    " Fold-style paginator helper for Smithy `@paginated` operations.\n"
    "\n"
    " The codegen-emitted `paginate_<op>` functions are thin wrappers\n"
    " over `fold`. Each generated paginator:\n"
    "\n"
    "   1. Builds a `step(cursor) -> Result(#(items, next_cursor), e)`\n"
    "      closure that injects the cursor into the typed input via\n"
    "      the `inputToken` field, invokes the operation, and projects\n"
    "      the `items` + `outputToken` fields out of the typed output.\n"
    "   2. Calls `fold(acc, step, reducer)` to drive the loop until\n"
    "      the step returns `None` for the next cursor.\n"
    "\n"
    " The helper deliberately doesn't depend on `gleam_yielder` or any\n"
    " lazy-stream package: a fold over a typed accumulator handles\n"
    " every paginated-list use case (count, collect, find-first, ...)\n"
    " without forcing a runtime dependency or special evaluation\n"
    " strategy.\n"
).

-file("src/aws/pagination.gleam", 44).
-spec loop(
    OUH,
    gleam@option:option(OUI),
    fun((gleam@option:option(OUI)) -> {ok,
            {list(OUL), gleam@option:option(OUI)}} |
        {error, OUO}),
    fun((OUH, list(OUL)) -> OUH)
) -> {ok, OUH} | {error, OUO}.
loop(Acc, Token, Step, Reducer) ->
    gleam@result:'try'(
        Step(Token),
        fun(_use0) ->
            {Items, Next} = _use0,
            Acc@1 = Reducer(Acc, Items),
            case Next of
                none ->
                    {ok, Acc@1};

                {some, _} ->
                    loop(Acc@1, Next, Step, Reducer)
            end
        end
    ).

-file("src/aws/pagination.gleam", 36).
?DOC(
    " Drive a Smithy `@paginated` operation to completion, folding each\n"
    " page's items into `acc` via `reducer`. The `step` closure receives\n"
    " the cursor returned by the previous page (or `None` on the first\n"
    " call) and must return `#(items, next_cursor)` for the page it just\n"
    " fetched. The loop stops when `step` returns `None` for the\n"
    " next-cursor — the canonical Smithy signal that pagination is\n"
    " exhausted. Errors from `step` propagate verbatim.\n"
    "\n"
    " `cursor` is parametric: most AWS services use `String` (`NextToken`,\n"
    " `Marker`, ...) but some carry richer values (DynamoDB's\n"
    " `LastEvaluatedKey` is a `Dict(String, AttributeValue)`). The helper\n"
    " stays agnostic — the codegen-emitted `paginate_<op>` wrapper\n"
    " instantiates `cursor` to match the operation's input/output token\n"
    " types.\n"
).
-spec fold(
    OTV,
    fun((gleam@option:option(OTW)) -> {ok,
            {list(OTY), gleam@option:option(OTW)}} |
        {error, OUB}),
    fun((OTV, list(OTY)) -> OTV)
) -> {ok, OTV} | {error, OUB}.
fold(Acc, Step, Reducer) ->
    loop(Acc, none, Step, Reducer).