-module(aws@internal@codec@rest). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/aws/internal/codec/rest.gleam"). -export([substitute_label/4, add_query/3, bool_to_query/1, int_to_query/1, float_to_query/1, maybe_set_list_header/3, append_content_encoding/2, idempotency_token/0, quote_list_string_entry/1, build_path/2, maybe_set_header/3, set_default_header/3, add_prefix_headers/3, add_query_params/2, add_query_params_list/2, timestamp_to_header/1, enum_wire_value/1, string_header/2, int_header/2, bool_header/2, float_header/2, enum_header/3, http_date_header/2, iso8601_header/2, epoch_seconds_header/2, with_content_md5_header/2, glacier_tree_hash/1, with_glacier_tree_hash_headers/2, checksum_header/2, with_checksum_header/3, checksum_algorithm_from_wire/1, with_checksum_header_for_wire/3]). -export_type([checksum_algorithm/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( " Shared runtime helpers for the rest-protocol emitters\n" " (restJson1, restXml). Holds the URI / query / header glue that\n" " generated `build_*_request` functions call into for each\n" " `@httpLabel`, `@httpQuery`, `@httpHeader` member.\n" ). -type checksum_algorithm() :: checksum_sha256 | checksum_sha1 | checksum_crc32 | checksum_crc32_c. -file("src/aws/internal/codec/rest.gleam", 41). ?DOC(" Encode each path segment but keep the `/` separators intact.\n"). -spec encode_path_preserve_slash(binary()) -> binary(). encode_path_preserve_slash(Path) -> _pipe = gleam@string:split(Path, <<"/"/utf8>>), _pipe@1 = gleam@list:map(_pipe, fun aws@internal@uri:encode_segment/1), gleam@string:join(_pipe@1, <<"/"/utf8>>). -file("src/aws/internal/codec/rest.gleam", 23). ?DOC( " Substitute a single `@httpLabel` member into the URI template.\n" " Templates use `{Name}` or `{Name+}` (the `+` marks a greedy label\n" " that may contain `/`). Values are percent-encoded; greedy labels\n" " preserve `/` in the value.\n" ). -spec substitute_label(binary(), binary(), binary(), boolean()) -> binary(). substitute_label(Template, Name, Value, Greedy) -> Placeholder = <<<<"{"/utf8, Name/binary>>/binary, "}"/utf8>>, Greedy_placeholder = <<<<"{"/utf8, Name/binary>>/binary, "+}"/utf8>>, Encoded = case Greedy of true -> encode_path_preserve_slash(Value); false -> aws@internal@uri:encode_segment(Value) end, _pipe = Template, _pipe@1 = gleam@string:replace(_pipe, Greedy_placeholder, Encoded), gleam@string:replace(_pipe@1, Placeholder, Encoded). -file("src/aws/internal/codec/rest.gleam", 49). ?DOC( " Append a query parameter pair. Returns the resulting query string\n" " (without the leading `?`); call sites prepend it themselves.\n" ). -spec add_query(binary(), binary(), binary()) -> binary(). add_query(Existing, Name, Value) -> Pair = <<<<(aws@internal@uri:encode_component(Name))/binary, "="/utf8>>/binary, (aws@internal@uri:encode_component(Value))/binary>>, case Existing of <<""/utf8>> -> Pair; _ -> <<<>/binary, Pair/binary>> end. -file("src/aws/internal/codec/rest.gleam", 58). ?DOC(" Bool → query value: \"true\" / \"false\".\n"). -spec bool_to_query(boolean()) -> binary(). bool_to_query(B) -> case B of true -> <<"true"/utf8>>; false -> <<"false"/utf8>> end. -file("src/aws/internal/codec/rest.gleam", 66). ?DOC(" Int → query / header value as decimal.\n"). -spec int_to_query(integer()) -> binary(). int_to_query(N) -> erlang:integer_to_binary(N). -file("src/aws/internal/codec/rest.gleam", 74). ?DOC( " Float → query / header / URI-label value. Uses Erlang's `short`\n" " formatter so `1.1` round-trips as the literal `\"1.1\"` — the AWS\n" " SimpleScalarProperties protocol-test corpus rejects scientific\n" " notation in these positions.\n" ). -spec float_to_query(float()) -> binary(). float_to_query(F) -> aws_ffi:float_short(F). -file("src/aws/internal/codec/rest.gleam", 84). ?DOC( " `@httpHeader` on a list member emits the values comma-joined, per\n" " HTTP/1.1 header-folding rules. `Some([\"a\", \"b\"])` becomes\n" " `Name: a, b`. Empty lists drop the header entirely.\n" ). -spec maybe_set_list_header( gleam@dict:dict(binary(), binary()), binary(), list(binary()) ) -> gleam@dict:dict(binary(), binary()). maybe_set_list_header(Headers, Name, Values) -> gleam@dict:insert(Headers, Name, gleam@string:join(Values, <<", "/utf8>>)). -file("src/aws/internal/codec/rest.gleam", 100). ?DOC( " Append a `@requestCompression` encoding to the `Content-Encoding`\n" " header. Existing encodings (e.g. caller-set `Content-Encoding:\n" " custom`) are preserved with the new value appended after a comma:\n" " `custom` + `gzip` ⇒ `custom, gzip`.\n" ). -spec append_content_encoding(gleam@dict:dict(binary(), binary()), binary()) -> gleam@dict:dict(binary(), binary()). append_content_encoding(Headers, Encoding) -> case gleam_stdlib:map_get(Headers, <<"Content-Encoding"/utf8>>) of {ok, Existing} -> gleam@dict:insert( Headers, <<"Content-Encoding"/utf8>>, <<<>/binary, Encoding/binary>> ); {error, _} -> gleam@dict:insert(Headers, <<"Content-Encoding"/utf8>>, Encoding) end. -file("src/aws/internal/codec/rest.gleam", 115). ?DOC( " Generated `@idempotencyToken` value, used when a request member\n" " with that trait is left as `Option.None`. Backed by the runtime\n" " FFI so tests can pin a deterministic UUID via `application:set_env`.\n" ). -spec idempotency_token() -> binary(). idempotency_token() -> aws_ffi:idempotency_token(). -file("src/aws/internal/codec/rest.gleam", 120). ?DOC( " RFC 7230 list-header quoting for string elements. Smithy applies\n" " this only to string-typed entries — timestamp values use the raw\n" " `Mon, 16 Dec ... GMT` form even though it contains a comma.\n" ). -spec quote_list_string_entry(binary()) -> binary(). quote_list_string_entry(V) -> case gleam_stdlib:contains_string(V, <<","/utf8>>) orelse gleam_stdlib:contains_string( V, <<"\""/utf8>> ) of true -> <<<<"\""/utf8, (gleam@string:replace(V, <<"\""/utf8>>, <<"\\\""/utf8>>))/binary>>/binary, "\""/utf8>>; false -> V end. -file("src/aws/internal/codec/rest.gleam", 134). ?DOC( " Build the full path: substitute labels, then append query (with `?`)\n" " if non-empty.\n" " Merge a path that may already carry a static query string (from the\n" " `@http` URI template, e.g. `/Foo?bar=baz`) with the dynamically\n" " built query string from `@httpQuery` members. Either or both can be\n" " empty. The static-query side wins on key order; dynamic params are\n" " appended.\n" ). -spec build_path(binary(), binary()) -> binary(). build_path(Uri_path, Query) -> {Path_only, Static_query} = case gleam@string:split_once( Uri_path, <<"?"/utf8>> ) of {ok, {P, Q}} -> {P, Q}; {error, _} -> {Uri_path, <<""/utf8>>} end, Combined = case {Static_query, Query} of {<<""/utf8>>, <<""/utf8>>} -> <<""/utf8>>; {<<""/utf8>>, Q@1} -> Q@1; {Sq, <<""/utf8>>} -> Sq; {Sq@1, Q@2} -> <<<>/binary, Q@2/binary>> end, case Combined of <<""/utf8>> -> Path_only; _ -> <<<>/binary, Combined/binary>> end. -file("src/aws/internal/codec/rest.gleam", 153). ?DOC( " Set a header on the headers dict if the value is non-empty (Smithy\n" " `@httpHeader` typically omits the header when the value is None).\n" ). -spec maybe_set_header(gleam@dict:dict(binary(), binary()), binary(), binary()) -> gleam@dict:dict(binary(), binary()). maybe_set_header(Headers, Name, Value) -> gleam@dict:insert(Headers, Name, Value). -file("src/aws/internal/codec/rest.gleam", 169). ?DOC( " Insert a service-level default header only when the caller hasn't\n" " already provided one with the same name. Mirrors `set_default_header`\n" " in the Rust SDK and the `contains_key` guard inside Glacier's\n" " `add_checksum_treehash` so caller `@httpHeader`-bound values win on\n" " collision.\n" ). -spec set_default_header( gleam@dict:dict(binary(), binary()), binary(), binary() ) -> gleam@dict:dict(binary(), binary()). set_default_header(Headers, Name, Value) -> case gleam@dict:has_key(Headers, Name) of true -> Headers; false -> gleam@dict:insert(Headers, Name, Value) end. -file("src/aws/internal/codec/rest.gleam", 182). ?DOC( " Iterate `@httpPrefixHeaders` map members: for each entry,\n" " emit a header `: `.\n" ). -spec add_prefix_headers( gleam@dict:dict(binary(), binary()), binary(), gleam@dict:dict(binary(), binary()) ) -> gleam@dict:dict(binary(), binary()). add_prefix_headers(Headers, Prefix, Entries) -> gleam@dict:fold( Entries, Headers, fun(Acc, K, V) -> gleam@dict:insert(Acc, <>, V) end ). -file("src/aws/internal/codec/rest.gleam", 191). ?DOC(" Iterate `@httpQueryParams` map members (Map).\n"). -spec add_query_params(binary(), gleam@dict:dict(binary(), binary())) -> binary(). add_query_params(Query, Entries) -> gleam@dict:fold(Entries, Query, fun(Acc, K, V) -> add_query(Acc, K, V) end). -file("src/aws/internal/codec/rest.gleam", 200). ?DOC( " Iterate `@httpQueryParams` map members (Map>).\n" " Each list value emits one query param per element.\n" ). -spec add_query_params_list(binary(), gleam@dict:dict(binary(), list(binary()))) -> binary(). add_query_params_list(Query, Entries) -> gleam@dict:fold( Entries, Query, fun(Acc, K, Vs) -> gleam@list:fold(Vs, Acc, fun(Q, V) -> add_query(Q, K, V) end) end ). -file("src/aws/internal/codec/rest.gleam", 214). ?DOC( " Format a timestamp for use in URI labels / query strings / headers.\n" " Smithy's default `@timestampFormat` for `date-time` (the\n" " restJson1 + restXml default) is RFC 3339, e.g. `2019-12-16T23:48:18Z`.\n" " We always emit Z-suffixed UTC; the wire form remains stable even if\n" " the input came from a system clock in a different zone.\n" ). -spec timestamp_to_header(integer()) -> binary(). timestamp_to_header(Epoch_seconds) -> aws_ffi:format_iso8601(Epoch_seconds). -file("src/aws/internal/codec/rest.gleam", 225). ?DOC( " Extract the raw wire string from a JSON-encoded enum value. The\n" " generated `encode__enum(v)` returns a `json.Json` like\n" " `json.string(\"VALUE\")`; URI / query / header position wants just\n" " `VALUE`. We render to JSON text and strip the surrounding quotes.\n" ). -spec enum_wire_value(gleam@json:json()) -> binary(). enum_wire_value(J) -> S = gleam@json:to_string(J), Len = string:length(S), case Len > 2 of true -> gleam@string:slice(S, 1, Len - 2); false -> S end. -file("src/aws/internal/codec/rest.gleam", 242). -spec string_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(binary()). string_header(Headers, Name) -> _pipe = gleam_stdlib:map_get(Headers, string:lowercase(Name)), gleam@option:from_result(_pipe). -file("src/aws/internal/codec/rest.gleam", 250). -spec int_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(integer()). int_header(Headers, Name) -> gleam@option:then(string_header(Headers, Name), fun(Raw) -> _pipe = Raw, _pipe@1 = gleam@string:trim(_pipe), _pipe@2 = gleam_stdlib:parse_int(_pipe@1), gleam@option:from_result(_pipe@2) end). -file("src/aws/internal/codec/rest.gleam", 258). -spec bool_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(boolean()). bool_header(Headers, Name) -> gleam@option:then( string_header(Headers, Name), fun(Raw) -> case string:lowercase(gleam@string:trim(Raw)) of <<"true"/utf8>> -> {some, true}; <<"false"/utf8>> -> {some, false}; _ -> none end end ). -file("src/aws/internal/codec/rest.gleam", 547). -spec parse_float(binary()) -> gleam@option:option(float()). parse_float(S) -> _pipe = gleam_stdlib:parse_float(S), _pipe@2 = gleam@result:lazy_or( _pipe, fun() -> _pipe@1 = gleam_stdlib:parse_int(S), gleam@result:map(_pipe@1, fun erlang:float/1) end ), gleam@option:from_result(_pipe@2). -file("src/aws/internal/codec/rest.gleam", 273). ?DOC( " Float header — used for shapes that bind a `Float` member to a\n" " response header. Falls through to `None` if the value can't be\n" " parsed; same forgiving contract as `int_header` / `bool_header`.\n" ). -spec float_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(float()). float_header(Headers, Name) -> gleam@option:then( string_header(Headers, Name), fun(Raw) -> parse_float(gleam@string:trim(Raw)) end ). -file("src/aws/internal/codec/rest.gleam", 288). ?DOC( " Enum header — looks up a string header, then runs the supplied\n" " `_from_wire` decoder. Falls through to `None` if the\n" " header is missing or the wire value doesn't match a known\n" " variant (forgiving contract — unknown variants don't crash\n" " the response parse). The codegen passes the generated\n" " `_from_wire` function directly so this stays\n" " enum-agnostic.\n" ). -spec enum_header( gleam@dict:dict(binary(), binary()), binary(), fun((binary()) -> {ok, MLR} | {error, binary()}) ) -> gleam@option:option(MLR). enum_header(Headers, Name, From_wire) -> case string_header(Headers, Name) of {some, S} -> case From_wire(S) of {ok, V} -> {some, V}; {error, _} -> none end; none -> none end. -file("src/aws/internal/codec/rest.gleam", 308). ?DOC( " HTTP-date header — RFC 7231 §7.1.1.1 form\n" " (`Tue, 29 Apr 2014 18:30:38 GMT`). The default `@timestampFormat`\n" " for header bindings per Smithy core — covers `Last-Modified`,\n" " `Expires`, `Date`, etc. Forgiving contract: missing header or\n" " unparseable string → `None`.\n" ). -spec http_date_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(aws@internal@codec@json_timestamp:timestamp()). http_date_header(Headers, Name) -> case string_header(Headers, Name) of {some, Raw} -> case aws@internal@codec@json_timestamp:parse_http_date( gleam@string:trim(Raw) ) of {ok, T} -> {some, T}; {error, _} -> none end; none -> none end. -file("src/aws/internal/codec/rest.gleam", 324). ?DOC( " ISO 8601 timestamp header (`@timestampFormat(\"date-time\")`,\n" " `2024-01-02T03:04:05Z`).\n" ). -spec iso8601_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(aws@internal@codec@json_timestamp:timestamp()). iso8601_header(Headers, Name) -> case string_header(Headers, Name) of {some, Raw} -> case aws@internal@codec@json_timestamp:parse_iso8601( gleam@string:trim(Raw) ) of {ok, T} -> {some, T}; {error, _} -> none end; none -> none end. -file("src/aws/internal/codec/rest.gleam", 341). ?DOC( " Epoch-seconds timestamp header\n" " (`@timestampFormat(\"epoch-seconds\")`, integer seconds since 1970\n" " in the header value).\n" ). -spec epoch_seconds_header(gleam@dict:dict(binary(), binary()), binary()) -> gleam@option:option(aws@internal@codec@json_timestamp:timestamp()). epoch_seconds_header(Headers, Name) -> case int_header(Headers, Name) of {some, N} -> {some, {timestamp, N, 0}}; none -> none end. -file("src/aws/internal/codec/rest.gleam", 366). ?DOC( " Set the `Content-MD5` header to `base64(md5(body))`. Used by the\n" " Smithy `smithy.api#httpChecksumRequired` trait — the codegen\n" " emits a call to this helper at the tail of `build__request`\n" " for any operation that carries the trait.\n" "\n" " Always overwrites a previous `Content-MD5` entry: the SDK is\n" " responsible for the canonical value, and a stale caller-supplied\n" " one would surface as a 400 from the service. Other headers pass\n" " through unchanged.\n" "\n" " MD5 is not a security primitive here. The wire contract requires\n" " it (S3-control + restJson1 protocol tests fix the exact bytes);\n" " SigV4 covers the actual auth on the request.\n" ). -spec with_content_md5_header(gleam@dict:dict(binary(), binary()), bitstring()) -> gleam@dict:dict(binary(), binary()). with_content_md5_header(Headers, Body) -> Digest = gleam_stdlib:base64_encode(aws_ffi:md5(Body), true), gleam@dict:insert(Headers, <<"Content-MD5"/utf8>>, Digest). -file("src/aws/internal/codec/rest.gleam", 446). -spec pair_hash(list(bitstring())) -> list(bitstring()). pair_hash(Hashes) -> case Hashes of [] -> []; [Single] -> [Single]; [Left, Right | Rest] -> [aws_ffi:sha256(gleam@bit_array:append(Left, Right)) | pair_hash(Rest)] end. -file("src/aws/internal/codec/rest.gleam", 439). -spec combine_tree_hashes(list(bitstring())) -> bitstring(). combine_tree_hashes(Hashes) -> case Hashes of [Single] -> Single; _ -> combine_tree_hashes(pair_hash(Hashes)) end. -file("src/aws/internal/codec/rest.gleam", 416). -spec chunk_hashes(bitstring(), integer(), list(bitstring())) -> list(bitstring()). chunk_hashes(Body, Chunk_size, Acc) -> case erlang:byte_size(Body) of 0 -> lists:reverse(Acc); Size -> Take = case Size > Chunk_size of true -> Chunk_size; false -> Size end, Chunk@1 = case gleam_stdlib:bit_array_slice(Body, 0, Take) of {ok, Chunk} -> Chunk; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"aws/internal/codec/rest"/utf8>>, function => <<"chunk_hashes"/utf8>>, line => 431, value => _assert_fail, start => 14691, 'end' => 14744, pattern_start => 14702, pattern_end => 14711}) end, Rest_size = Size - Take, Rest@1 = case gleam_stdlib:bit_array_slice(Body, Take, Rest_size) of {ok, Rest} -> Rest; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"aws/internal/codec/rest"/utf8>>, function => <<"chunk_hashes"/utf8>>, line => 433, value => _assert_fail@1, start => 14785, 'end' => 14845, pattern_start => 14796, pattern_end => 14804}) end, chunk_hashes(Rest@1, Chunk_size, [aws_ffi:sha256(Chunk@1) | Acc]) end. -file("src/aws/internal/codec/rest.gleam", 406). ?DOC( " Compute the Glacier tree hash of `body` as raw bytes (caller\n" " hex-encodes for the wire). Empty body degenerates to\n" " `SHA-256(\"\")` so the function is total. Matches\n" " `glacier_interceptors::compute_hash_tree` in the Rust SDK.\n" ). -spec glacier_tree_hash(bitstring()) -> bitstring(). glacier_tree_hash(Body) -> case erlang:byte_size(Body) of 0 -> aws_ffi:sha256(<<>>); _ -> Chunks = chunk_hashes(Body, 1048576, []), combine_tree_hashes(Chunks) end. -file("src/aws/internal/codec/rest.gleam", 389). ?DOC( " Glacier's tree-hash + content-sha256 headers. Both end up as the\n" " Computed against the recursive 1 MiB chunk algorithm at\n" " https://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-\n" " calculations.html: split the body into 1 MiB chunks, SHA-256 each,\n" " then pair-hash adjacent digests until one remains. Single-chunk\n" " bodies degenerate to plain SHA-256 (tree-hash == content-sha256),\n" " which is what every Glacier protocol-test fixture happens to use,\n" " but the recursive form is required for the > 1 MiB upload archive\n" " path used by real callers.\n" "\n" " `X-Amz-Sha256-Tree-Hash` carries the tree-hash digest;\n" " `X-Amz-Content-Sha256` carries the full-body SHA-256. The Rust SDK\n" " uses the same pair of headers in `glacier_interceptors::\n" " add_checksum_treehash`. Both are skipped when already present so a\n" " caller-supplied value wins.\n" ). -spec with_glacier_tree_hash_headers( gleam@dict:dict(binary(), binary()), bitstring() ) -> gleam@dict:dict(binary(), binary()). with_glacier_tree_hash_headers(Headers, Body) -> Content_sha256 = aws_ffi:hex_encode(aws_ffi:sha256(Body)), Tree_hash = aws_ffi:hex_encode(glacier_tree_hash(Body)), _pipe = Headers, _pipe@1 = set_default_header( _pipe, <<"X-Amz-Sha256-Tree-Hash"/utf8>>, Tree_hash ), set_default_header(_pipe@1, <<"X-Amz-Content-Sha256"/utf8>>, Content_sha256). -file("src/aws/internal/codec/rest.gleam", 475). ?DOC( " `(header_name, base64_digest)` pair for a body checksum. The\n" " header name follows the AWS convention `x-amz-checksum-`\n" " (lowercase). The digest is base64 of the raw bytes — same\n" " padding rules as `Content-MD5`. Pure function; the\n" " `aws.protocols#httpChecksum` middleware in the codegen layer\n" " calls this and inserts the result into the request headers.\n" ). -spec checksum_header(checksum_algorithm(), bitstring()) -> {binary(), binary()}. checksum_header(Algorithm, Body) -> case Algorithm of checksum_sha256 -> {<<"x-amz-checksum-sha256"/utf8>>, gleam_stdlib:base64_encode(aws_ffi:sha256(Body), true)}; checksum_sha1 -> {<<"x-amz-checksum-sha1"/utf8>>, gleam_stdlib:base64_encode(aws_ffi:sha1(Body), true)}; checksum_crc32 -> {<<"x-amz-checksum-crc32"/utf8>>, gleam_stdlib:base64_encode( aws@internal@crypto:crc32_be_bytes(erlang:crc32(Body)), true )}; checksum_crc32_c -> {<<"x-amz-checksum-crc32c"/utf8>>, gleam_stdlib:base64_encode( aws@internal@crypto:crc32_be_bytes(aws_ffi:crc32c(Body)), true )} end. -file("src/aws/internal/codec/rest.gleam", 503). ?DOC( " Add an `x-amz-checksum-` header to the request. Convenience\n" " wrapper around `checksum_header` that lets call sites stay\n" " pipeline-style with the existing `Dict(String, String)` header\n" " shape — same ergonomics as `with_content_md5_header`.\n" ). -spec with_checksum_header( gleam@dict:dict(binary(), binary()), checksum_algorithm(), bitstring() ) -> gleam@dict:dict(binary(), binary()). with_checksum_header(Headers, Algorithm, Body) -> {Name, Value} = checksum_header(Algorithm, Body), gleam@dict:insert(Headers, Name, Value). -file("src/aws/internal/codec/rest.gleam", 519). ?DOC( " Translate a Smithy `ChecksumAlgorithm` enum's wire value\n" " (e.g. `\"SHA256\"`, `\"CRC32C\"`) to the runtime `ChecksumAlgorithm`\n" " variant, falling back to `ChecksumSha256` when the wire value\n" " doesn't match a supported algorithm. Used by the codegen's\n" " algorithm-member dispatch for `aws.protocols#httpChecksum` so\n" " generated request builders can read the caller's typed enum\n" " choice without needing a per-service jump table.\n" ). -spec checksum_algorithm_from_wire(binary()) -> checksum_algorithm(). checksum_algorithm_from_wire(Wire) -> case Wire of <<"SHA256"/utf8>> -> checksum_sha256; <<"SHA1"/utf8>> -> checksum_sha1; <<"CRC32"/utf8>> -> checksum_crc32; <<"CRC32C"/utf8>> -> checksum_crc32_c; _ -> checksum_sha256 end. -file("src/aws/internal/codec/rest.gleam", 539). ?DOC( " Add the `x-amz-checksum-` header using a wire-form\n" " algorithm name. Equivalent to\n" " `with_checksum_header(headers, checksum_algorithm_from_wire(wire), body)`.\n" " Exists so the codegen can emit a single call that takes the\n" " generated enum's wire-encoder output directly, without\n" " needing per-service algorithm-mapping helpers.\n" ). -spec with_checksum_header_for_wire( gleam@dict:dict(binary(), binary()), binary(), bitstring() ) -> gleam@dict:dict(binary(), binary()). with_checksum_header_for_wire(Headers, Wire, Body) -> with_checksum_header(Headers, checksum_algorithm_from_wire(Wire), Body).