-module(multipartkit@internal@scan). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/multipartkit/internal/scan.gleam"). -export([dash_pattern/1, find_delimiter/3]). -export_type([delim_kind/0, scan_outcome/0, after_class/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 delim_kind() :: delimiter | closing. -type scan_outcome() :: {found, integer(), delim_kind(), integer()} | incomplete. -type after_class() :: {class_delimiter, integer()} | {class_closing, integer()} | class_invalid | class_incomplete. -file("src/multipartkit/internal/scan.gleam", 32). ?DOC(false). -spec dash_pattern(binary()) -> bitstring(). dash_pattern(Boundary) -> gleam@bit_array:append(<<"--"/utf8>>, gleam_stdlib:identity(Boundary)). -file("src/multipartkit/internal/scan.gleam", 72). ?DOC(false). -spec is_at_line_start(bitstring(), integer()) -> boolean(). is_at_line_start(Buf, P) -> case P of 0 -> true; _ -> case gleam_stdlib:bit_array_slice(Buf, P - 1, 1) of {ok, <<10>>} -> true; _ -> false end end. -file("src/multipartkit/internal/scan.gleam", 83). ?DOC(false). -spec body_end_for(bitstring(), integer()) -> integer(). body_end_for(Buf, P) -> case P of 0 -> 0; _ -> case (P >= 2) andalso (gleam_stdlib:bit_array_slice(Buf, P - 2, 2) =:= {ok, <<"\r\n"/utf8>>}) of true -> P - 2; false -> case gleam_stdlib:bit_array_slice(Buf, P - 1, 1) of {ok, <<10>>} -> P - 1; _ -> P end end end. -file("src/multipartkit/internal/scan.gleam", 156). ?DOC(false). -spec skip_lwsp(bitstring(), integer(), integer()) -> integer(). skip_lwsp(Buf, At, Total) -> case At >= Total of true -> At; false -> case gleam_stdlib:bit_array_slice(Buf, At, 1) of {ok, <<32>>} -> skip_lwsp(Buf, At + 1, Total); {ok, <<9>>} -> skip_lwsp(Buf, At + 1, Total); _ -> At end end. -file("src/multipartkit/internal/scan.gleam", 140). ?DOC(false). -spec consume_closing_tail(bitstring(), integer(), integer()) -> integer(). consume_closing_tail(Buf, At, Total) -> After_padding = skip_lwsp(Buf, At, Total), case After_padding >= Total of true -> After_padding; false -> case gleam_stdlib:bit_array_slice(Buf, After_padding, 2) of {ok, <<"\r\n"/utf8>>} -> After_padding + 2; _ -> case gleam_stdlib:bit_array_slice(Buf, After_padding, 1) of {ok, <<10>>} -> After_padding + 1; _ -> After_padding end end end. -file("src/multipartkit/internal/scan.gleam", 106). ?DOC(false). -spec classify_after(bitstring(), integer(), integer()) -> after_class(). classify_after(Buf, At, Total) -> case At >= Total of true -> class_incomplete; false -> After_padding = skip_lwsp(Buf, At, Total), case gleam_stdlib:bit_array_slice(Buf, After_padding, 2) of {ok, <<"--"/utf8>>} -> {class_closing, consume_closing_tail(Buf, After_padding + 2, Total)}; {ok, <<"\r\n"/utf8>>} -> {class_delimiter, After_padding + 2}; {ok, <<10, _>>} -> {class_delimiter, After_padding + 1}; _ -> case gleam_stdlib:bit_array_slice(Buf, After_padding, 1) of {ok, <<10>>} -> {class_delimiter, After_padding + 1}; {ok, _} -> case (After_padding + 2) > Total of true -> class_incomplete; false -> class_invalid end; {error, nil} -> case After_padding >= Total of true -> class_incomplete; false -> class_invalid end end end end. -file("src/multipartkit/internal/scan.gleam", 47). ?DOC(false). -spec scan_loop(bitstring(), bitstring(), integer(), integer()) -> scan_outcome(). scan_loop(Buf, Pattern, From, Total) -> case multipartkit@internal@bytes:find_index(Buf, Pattern, From) of {error, nil} -> incomplete; {ok, P} -> case is_at_line_start(Buf, P) of false -> scan_loop(Buf, Pattern, P + 1, Total); true -> Body_end_excl = body_end_for(Buf, P), After_pattern = P + erlang:byte_size(Pattern), case classify_after(Buf, After_pattern, Total) of {class_delimiter, After} -> {found, Body_end_excl, delimiter, After}; {class_closing, After@1} -> {found, Body_end_excl, closing, After@1}; class_invalid -> scan_loop(Buf, Pattern, P + 1, Total); class_incomplete -> incomplete end end end. -file("src/multipartkit/internal/scan.gleam", 38). ?DOC(false). -spec find_delimiter(bitstring(), bitstring(), integer()) -> scan_outcome(). find_delimiter(Buf, Pattern, From) -> Total = erlang:byte_size(Buf), scan_loop(Buf, Pattern, From, Total).