-module(multipartkit@internal@headers). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/multipartkit/internal/headers.gleam"). -export([parse_block/1, derive_meta/1]). -export_type([derived_meta/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 derived_meta() :: {derived_meta, gleam@option:option(binary()), gleam@option:option(binary()), gleam@option:option(binary())}. -file("src/multipartkit/internal/headers.gleam", 30). ?DOC(false). -spec drop_trailing_empty(list(binary())) -> list(binary()). drop_trailing_empty(Lines) -> case lists:reverse(Lines) of [<<""/utf8>> | Rest] -> lists:reverse(Rest); _ -> Lines end. -file("src/multipartkit/internal/headers.gleam", 73). ?DOC(false). -spec trim_trailing_ows(binary()) -> binary(). trim_trailing_ows(Value) -> case gleam_stdlib:string_ends_with(Value, <<" "/utf8>>) orelse gleam_stdlib:string_ends_with( Value, <<"\t"/utf8>> ) of false -> Value; true -> case string:length(Value) of 0 -> Value; N -> trim_trailing_ows(gleam@string:slice(Value, 0, N - 1)) end end. -file("src/multipartkit/internal/headers.gleam", 68). ?DOC(false). -spec trim_ows(binary()) -> binary(). trim_ows(Value) -> Leading = multipartkit@internal@text:skip_ows(Value), trim_trailing_ows(Leading). -file("src/multipartkit/internal/headers.gleam", 51). ?DOC(false). -spec parse_line(binary()) -> {ok, {binary(), binary()}} | {error, multipartkit@error:multipart_error()}. parse_line(Line) -> case gleam_stdlib:string_starts_with(Line, <<" "/utf8>>) orelse gleam_stdlib:string_starts_with( Line, <<"\t"/utf8>> ) of true -> {error, {invalid_header, Line}}; false -> case gleam@string:split_once(Line, <<":"/utf8>>) of {error, nil} -> {error, {invalid_header, Line}}; {ok, {Name, Value}} -> case Name of <<""/utf8>> -> {error, {invalid_header, Line}}; _ -> {ok, {Name, trim_ows(Value)}} end end end. -file("src/multipartkit/internal/headers.gleam", 37). ?DOC(false). -spec parse_lines(list(binary()), list({binary(), binary()})) -> {ok, list({binary(), binary()})} | {error, multipartkit@error:multipart_error()}. parse_lines(Lines, Acc) -> case Lines of [] -> {ok, lists:reverse(Acc)}; [Line | Rest] -> case parse_line(Line) of {error, Err} -> {error, Err}; {ok, Entry} -> parse_lines(Rest, [Entry | Acc]) end end. -file("src/multipartkit/internal/headers.gleam", 16). ?DOC(false). -spec parse_block(bitstring()) -> {ok, list({binary(), binary()})} | {error, multipartkit@error:multipart_error()}. parse_block(Block) -> case gleam@bit_array:to_string(Block) of {error, _} -> {error, {invalid_header, <<""/utf8>>}}; {ok, Text_block} -> Normalized = gleam@string:replace( Text_block, <<"\r\n"/utf8>>, <<"\n"/utf8>> ), Lines = gleam@string:split(Normalized, <<"\n"/utf8>>), Lines@1 = drop_trailing_empty(Lines), parse_lines(Lines@1, []) end. -file("src/multipartkit/internal/headers.gleam", 125). ?DOC(false). -spec first_header_ci(list({binary(), binary()}), binary()) -> gleam@option:option(binary()). first_header_ci(Headers, Name) -> case Headers of [] -> none; [{K, V} | Rest] -> case multipartkit@internal@text:equals_ci(K, Name) of true -> {some, V}; false -> first_header_ci(Rest, Name) end end. -file("src/multipartkit/internal/headers.gleam", 96). ?DOC(false). -spec derive_meta(list({binary(), binary()})) -> {ok, derived_meta()} | {error, multipartkit@error:multipart_error()}. derive_meta(Headers) -> Cd = first_header_ci(Headers, <<"content-disposition"/utf8>>), Ct = first_header_ci(Headers, <<"content-type"/utf8>>), case Cd of none -> {ok, {derived_meta, none, none, Ct}}; {some, Value} -> case multipartkit@content_disposition:parse(Value) of {error, _} -> {error, {invalid_content_disposition, Value}}; {ok, Parsed} -> {Name, Filename} = case multipartkit@content_disposition:disposition( Parsed ) of <<"form-data"/utf8>> -> {multipartkit@content_disposition:name(Parsed), multipartkit@content_disposition:filename( Parsed )}; _ -> {none, none} end, {ok, {derived_meta, Name, Filename, Ct}} end end.