-module(aws@internal@error_code).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/internal/error_code.gleam").
-export([normalise/1, from_header_value_and_body/2, from_headers_and_body/2]).
-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(
" Shared modeled-error-code extraction. AWS error responses carry the\n"
" modeled error *code* (the Smithy shape's local name) in one of three\n"
" places, depending on protocol: the `X-Amzn-Errortype` header\n"
" (awsJson*, restJson1), a JSON body `__type` / `code` field, or a\n"
" restXml `<Code>` element. This module pulls that local shape name\n"
" out — namespace prefix, URI suffix, and Smithy `[Charlie,foo]`\n"
" disambiguation suffix all stripped.\n"
"\n"
" Both the retry middleware (`aws/retry`), which inspects the raw\n"
" `Response` *inside* the retry loop before any typed parsing, and the\n"
" runtime (`aws/internal/client/runtime`), which builds the typed\n"
" `ServiceError` *after* the loop, need the same extraction — so it\n"
" lives here once rather than being duplicated across the two layers.\n"
).
-file("src/aws/internal/error_code.gleam", 57).
?DOC(
" Strip an error-type wire value down to its local Smithy shape name:\n"
" drop any `Type:uri` suffix, any `,` disambiguation list, and any\n"
" `namespace#` prefix. Exposed so callers that already hold a raw\n"
" header value (not a full response) can normalise it consistently.\n"
).
-spec normalise(binary()) -> binary().
normalise(Raw) ->
S = case gleam@string:split_once(Raw, <<":"/utf8>>) of
{ok, {Prefix, _}} ->
Prefix;
{error, _} ->
Raw
end,
S@1 = case gleam@string:split_once(S, <<","/utf8>>) of
{ok, {Prefix@1, _}} ->
Prefix@1;
{error, _} ->
S
end,
case gleam@string:split_once(S@1, <<"#"/utf8>>) of
{ok, {_, Local}} ->
Local;
{error, _} ->
S@1
end.
-file("src/aws/internal/error_code.gleam", 90).
?DOC(
" Pull the error code out of a restXml error body. Two shapes appear\n"
" in the wild — S3-style `<Error><Code>NoSuchBucket</Code>...</Error>`\n"
" and SQS/SNS-style `<ErrorResponse><Error><Code>X</Code>...</Error>`.\n"
" In both, the first `<Code>` element holds the error type, so a\n"
" single text search covers both without dragging in the full XML\n"
" decoder. The trim + empty-check rejects `<Code/>` / `<Code> </Code>`\n"
" so the fallback to \"Unknown\" still fires for malformed bodies.\n"
).
-spec from_xml(binary()) -> {ok, binary()} | {error, nil}.
from_xml(Body) ->
gleam@result:'try'(
aws@internal@text_scan:xml_tag_text(Body, <<"Code"/utf8>>),
fun(Raw) -> case gleam@string:trim(Raw) of
<<""/utf8>> ->
{error, nil};
Non_empty ->
{ok, Non_empty}
end end
).
-file("src/aws/internal/error_code.gleam", 72).
-spec from_body(binary()) -> binary().
from_body(Body) ->
Found = begin
_pipe = aws@internal@text_scan:json_string_after_key(
Body,
<<"__type"/utf8>>
),
_pipe@1 = gleam@result:lazy_or(
_pipe,
fun() ->
aws@internal@text_scan:json_string_after_key(
Body,
<<"code"/utf8>>
)
end
),
gleam@result:lazy_or(_pipe@1, fun() -> from_xml(Body) end)
end,
case Found of
{ok, V} ->
normalise(V);
{error, _} ->
<<"Unknown"/utf8>>
end.
-file("src/aws/internal/error_code.gleam", 39).
?DOC(
" Like `from_headers_and_body` but taking the `x-amzn-errortype`\n"
" header value as a pre-resolved `Result`. The retry layer holds a\n"
" `Response` (not a header dict) and reads the header via\n"
" `response.get_header`, so this entry point lets it reuse the exact\n"
" same extraction without rebuilding a dict.\n"
).
-spec from_header_value_and_body({ok, binary()} | {error, nil}, bitstring()) -> binary().
from_header_value_and_body(Error_type_header, Body) ->
case Error_type_header of
{ok, V} ->
normalise(V);
{error, _} ->
case gleam@bit_array:to_string(Body) of
{error, _} ->
<<"Unknown"/utf8>>;
{ok, Text} ->
from_body(Text)
end
end.
-file("src/aws/internal/error_code.gleam", 27).
?DOC(
" Pull the wire-error-type local name out of an error response's\n"
" already-lowercased headers + body. Prefers the `x-amzn-errortype`\n"
" header (restJson1, awsJson*), then falls back to the body's\n"
" `__type` / `code` (JSON) or `<Code>` (restXml). Returns the *local*\n"
" shape name with namespace / URI / disambiguation suffixes stripped,\n"
" or `\"Unknown\"` when nothing matches.\n"
).
-spec from_headers_and_body(gleam@dict:dict(binary(), binary()), bitstring()) -> binary().
from_headers_and_body(Headers, Body) ->
from_header_value_and_body(
gleam_stdlib:map_get(Headers, <<"x-amzn-errortype"/utf8>>),
Body
).