-module(ewe@internal@stream@chunked). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/ewe/internal/stream/chunked.gleam"). -export([send_response/3, start/5, send_chunk/3]). -export_type([chunked_body/0, chunked_next/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(false). -type chunked_body() :: {chunked_body, glisten@transport:transport(), glisten@socket:socket()}. -type chunked_next(MIL) :: {continue, MIL} | normal_stop | {abnormal_stop, binary()}. -file("src/ewe/internal/stream/chunked.gleam", 38). ?DOC(false). -spec send_response( gleam@http@response:response(any()), glisten@transport:transport(), glisten@socket:socket() ) -> {ok, nil} | {error, nil}. send_response(Resp, Transport, Socket) -> _pipe = case gleam@http@response:get_header( Resp, <<"transfer-encoding"/utf8>> ) of {ok, <<"chunked"/utf8>>} -> Resp; _ -> gleam@http@response:set_header( Resp, <<"transfer-encoding"/utf8>>, <<"chunked"/utf8>> ) end, _pipe@1 = ewe@internal@encoder:setup_encoded_response(_pipe), _pipe@2 = glisten@transport:send(Transport, Socket, _pipe@1), gleam@result:replace_error(_pipe@2, nil). -file("src/ewe/internal/stream/chunked.gleam", 131). ?DOC(false). -spec send_end(glisten@transport:transport(), glisten@socket:socket()) -> {ok, nil} | {error, glisten@socket:socket_reason()}. send_end(Transport, Socket) -> glisten@transport:send( Transport, Socket, gleam@bytes_tree:from_bit_array(<<"0\r\n\r\n"/utf8>>) ). -file("src/ewe/internal/stream/chunked.gleam", 139). ?DOC(false). -spec after_start( gleam@otp@actor:started(gleam@erlang@process:subject(any())), glisten@transport:transport(), glisten@socket:socket() ) -> gleam@otp@actor:started(nil). after_start(Started, Transport, Socket) -> Pid@1 = case gleam@erlang@process:subject_owner(erlang:element(3, Started)) of {ok, Pid} -> Pid; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"ewe/internal/stream/chunked"/utf8>>, function => <<"after_start"/utf8>>, line => 144, value => _assert_fail, start => 4297, 'end' => 4353, pattern_start => 4308, pattern_end => 4315}) end, _ = glisten@transport:controlling_process(Transport, Socket, Pid@1), {started, erlang:element(2, Started), nil}. -file("src/ewe/internal/stream/chunked.gleam", 53). ?DOC(false). -spec start( glisten@transport:transport(), glisten@socket:socket(), fun((gleam@erlang@process:subject(MIQ)) -> MIS), fun((chunked_body(), MIS, MIQ) -> chunked_next(MIS)), fun((chunked_body(), MIS) -> nil) ) -> {ok, gleam@otp@actor:started(nil)} | {error, gleam@otp@actor:start_error()}. start(Transport, Socket, On_init, Handler, On_close) -> _pipe@4 = gleam@otp@actor:new_with_initialiser( 1000, fun(_) -> Subject = gleam@erlang@process:new_subject(), State = On_init(Subject), Selector = begin _pipe = gleam_erlang_ffi:new_selector(), gleam@erlang@process:select(_pipe, Subject) end, _pipe@1 = gleam@otp@actor:initialised(State), _pipe@2 = gleam@otp@actor:returning(_pipe@1, Subject), _pipe@3 = gleam@otp@actor:selecting(_pipe@2, Selector), {ok, _pipe@3} end ), _pipe@5 = gleam@otp@actor:on_message( _pipe@4, fun(State@1, Message) -> Conn = {chunked_body, Transport, Socket}, case Handler(Conn, State@1, Message) of {continue, New_state} -> gleam@otp@actor:continue(New_state); normal_stop -> case send_end(Transport, Socket) of {ok, nil} -> On_close(Conn, State@1), gleam@otp@actor:stop(); {error, Socket_reason} -> logging:log( error, <<"Failed to send end of chunked response: "/utf8, (gleam@string:inspect(Socket_reason))/binary>> ), On_close(Conn, State@1), gleam@otp@actor:stop_abnormal( <<"Failed to send end of chunked response: "/utf8, (gleam@string:inspect(Socket_reason))/binary>> ) end; {abnormal_stop, Reason} -> logging:log( error, <<"Chunked response stopped abnormally: "/utf8, Reason/binary>> ), On_close(Conn, State@1), gleam@otp@actor:stop_abnormal(Reason) end end ), _pipe@6 = gleam@otp@actor:start(_pipe@5), gleam@result:map( _pipe@6, fun(_capture) -> after_start(_capture, Transport, Socket) end ). -file("src/ewe/internal/stream/chunked.gleam", 151). ?DOC(false). -spec to_hex_string(integer()) -> binary(). to_hex_string(Integer) -> erlang:integer_to_list(Integer, 16). -file("src/ewe/internal/stream/chunked.gleam", 113). ?DOC(false). -spec send_chunk( glisten@transport:transport(), glisten@socket:socket(), bitstring() ) -> {ok, nil} | {error, glisten@socket:socket_reason()}. send_chunk(Transport, Socket, Chunk) -> _pipe = gleam@bytes_tree:new(), _pipe@1 = gleam@bytes_tree:append_string( _pipe, to_hex_string(erlang:byte_size(Chunk)) ), _pipe@2 = gleam@bytes_tree:append(_pipe@1, <<"\r\n"/utf8>>), _pipe@3 = gleam@bytes_tree:append(_pipe@2, Chunk), _pipe@4 = gleam@bytes_tree:append(_pipe@3, <<"\r\n"/utf8>>), glisten@transport:send(Transport, Socket, _pipe@4).