Skip to main content

src/internal@encoder.erl

-module(internal@encoder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/internal/encoder.gleam").
-export([encode_email_address/2, encode_string/6, determine_encoding_order/4, name/1]).

-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(
    "/ Email content encoding utilities for MIME messages.\n"
    "/ This module provides functions for encoding email addresses and strings\n"
    "/ using various MIME content transfer encodings such as Base64, Quoted-Printable,\n"
    "/ and others defined in RFC standards.\n"
).

-file("src/internal/encoder.gleam", 22).
?DOC(" Encodes an email address using IDNA (Internationalized Domain Names in Applications).\n").
-spec encode_email_address(binary(), internal@encoder@encoding:encoding_mode()) -> {ok,
        binary()} |
    {error, internal@encoder@encoding:encoder_error()}.
encode_email_address(Address, Mode) ->
    internal@encoder@idna:encode_email_address(Address, Mode).

-file("src/internal/encoder.gleam", 32).
?DOC(
    " Encodes a string using the specified content transfer encoding.\n"
    "\n"
    " This function delegates to the appropriate encoder based on the encoding type.\n"
).
-spec encode_string(
    binary(),
    internal@encoder@encoding:encoding(),
    internal@encoder@encoding:encoding_mode(),
    integer(),
    integer(),
    integer()
) -> {ok, list(binary())} | {error, internal@encoder@encoding:encoder_error()}.
encode_string(String, Encoding, Mode, Position, Preferred_size, Maximum_size) ->
    case Encoding of
        base64 ->
            internal@encoder@base64:encode_string(
                String,
                Position,
                Preferred_size
            );

        {bit, Bits} ->
            internal@encoder@bit:encode_string(String, Bits, Mode, Maximum_size);

        percent_encoding ->
            internal@encoder@percent_encoding:encode_string(
                String,
                Position,
                Preferred_size
            );

        {quoted_printable, Rfc} ->
            internal@encoder@quoted_printable:encode_string(
                String,
                Rfc,
                Position,
                Preferred_size
            );

        {text, Field_type} ->
            internal@encoder@text:encode_string(
                String,
                Field_type,
                Mode,
                Position,
                Preferred_size,
                Maximum_size
            )
    end.

-file("src/internal/encoder.gleam", 91).
-spec estimate_encoded_size(
    internal@encoder@encoding:encoding(),
    internal@encoder@encoding:encoding_mode(),
    binary(),
    integer()
) -> {ok, integer()} | {error, internal@encoder@encoding:encoder_error()}.
estimate_encoded_size(Encoding, Mode, Value, Maximum_size) ->
    case Encoding of
        base64 ->
            internal@encoder@base64:estimate_encoded_size(Value);

        {bit, Bits} ->
            internal@encoder@bit:estimate_encoded_size(
                Value,
                Bits,
                Mode,
                Maximum_size
            );

        percent_encoding ->
            internal@encoder@percent_encoding:estimate_encoded_size(
                Value,
                Maximum_size
            );

        {quoted_printable, Rfc} ->
            internal@encoder@quoted_printable:estimate_encoded_size(Value, Rfc);

        {text, Field_type} ->
            internal@encoder@text:estimate_encoded_size(
                Value,
                Field_type,
                Mode,
                Maximum_size
            )
    end.

-file("src/internal/encoder.gleam", 63).
?DOC(
    " Determines the optimal order of encodings to try for encoding a string within a size limit.\n"
    "\n"
    " Estimates the encoded size for each encoding and returns them sorted by size\n"
    " from smallest to largest, filtering out encodings that would exceed the maximum size.\n"
    " This is useful for content negotiation to find the most efficient encoding.\n"
).
-spec determine_encoding_order(
    list(internal@encoder@encoding:encoding()),
    binary(),
    internal@encoder@encoding:encoding_mode(),
    integer()
) -> list(internal@encoder@encoding:encoding()).
determine_encoding_order(Encodings, String, Mode, Maximum_size) ->
    _pipe = Encodings,
    _pipe@3 = gleam@list:map(_pipe, fun(Encoding) -> _pipe@1 = Encoding,
            _pipe@2 = estimate_encoded_size(_pipe@1, Mode, String, Maximum_size),
            gleam@result:map(_pipe@2, fun(Size) -> {Encoding, Size} end) end),
    _pipe@4 = gleam@result:values(_pipe@3),
    _pipe@5 = gleam@list:sort(
        _pipe@4,
        fun(A, B) ->
            gleam@int:compare(gleam@pair:second(A), gleam@pair:second(B))
        end
    ),
    gleam@list:map(_pipe@5, fun gleam@pair:first/1).

-file("src/internal/encoder.gleam", 81).
?DOC(" Returns the canonical string name for an encoding type.\n").
-spec name(internal@encoder@encoding:encoding()) -> binary().
name(Encoding) ->
    case Encoding of
        base64 ->
            <<"base64"/utf8>>;

        {bit, Bits} ->
            <<(erlang:integer_to_binary(Bits))/binary, "bit"/utf8>>;

        percent_encoding ->
            <<"percent-encoding"/utf8>>;

        {quoted_printable, _} ->
            <<"quoted-printable"/utf8>>;

        {text, _} ->
            <<"quoted-string"/utf8>>
    end.