-module(ewe@internal@gramps@websocket). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/ewe/internal/gramps/websocket.gleam"). -export([text_frame/1, binary_frame/1, match_data_frame/3, decode_frame/2, apply_mask/2, encode_close_frame/2, encode_continuation_frame/3, apply_deflate/2, apply_inflate/2, encode_text_frame/3, encode_binary_frame/3, encode_ping_frame/2, encode_pong_frame/2, decode_many_frames/3, decode_many_frames_result/3, aggregate_frames/4, make_client_key/0, has_deflate/1, get_context_takeovers/1, parse_websocket_key/1]). -export_type([data_frame/0, close_reason/0, control_frame/0, frame/0, frame_parse_error/0, parsed_frame/0, compression/0, many_frames_parse_error/0, sha_hash/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). -opaque data_frame() :: {text_frame, bitstring()} | {binary_frame, bitstring()} | {compressed_text_frame, bitstring()} | {compressed_binary_frame, bitstring()}. -type close_reason() :: not_provided | {normal, bitstring()} | {going_away, bitstring()} | {protocol_error, bitstring()} | {unexpected_data_type, bitstring()} | {inconsistent_data_type, bitstring()} | {policy_violation, bitstring()} | {message_too_big, bitstring()} | {missing_extensions, bitstring()} | {unexpected_condition, bitstring()} | {custom_close_reason, integer(), bitstring()}. -type control_frame() :: {close_frame, close_reason()} | {ping_frame, bitstring()} | {pong_frame, bitstring()}. -type frame() :: {data, data_frame()} | {control, control_frame()} | {continuation, integer(), bitstring()}. -type frame_parse_error() :: {need_more_data, bitstring()} | invalid_frame. -type parsed_frame() :: {complete, frame()} | {incomplete, frame()}. -type compression() :: compressed | uncompressed. -type many_frames_parse_error() :: {need_more_data_accumulated, list(parsed_frame()), bitstring()} | contains_invalid_frame. -type sha_hash() :: sha. -file("src/ewe/internal/gramps/websocket.gleam", 24). ?DOC(false). -spec text_frame(bitstring()) -> data_frame(). text_frame(Payload) -> {text_frame, Payload}. -file("src/ewe/internal/gramps/websocket.gleam", 28). ?DOC(false). -spec binary_frame(bitstring()) -> data_frame(). binary_frame(Payload) -> {binary_frame, Payload}. -file("src/ewe/internal/gramps/websocket.gleam", 32). ?DOC(false). -spec match_data_frame( data_frame(), fun((bitstring(), boolean()) -> KIW), fun((bitstring(), boolean()) -> KIW) ) -> KIW. match_data_frame(Data_frame, On_text, On_binary) -> case Data_frame of {text_frame, Payload} -> On_text(Payload, false); {compressed_text_frame, Payload@1} -> On_text(Payload@1, true); {binary_frame, Payload@2} -> On_binary(Payload@2, false); {compressed_binary_frame, Payload@3} -> On_binary(Payload@3, true) end. -file("src/ewe/internal/gramps/websocket.gleam", 88). ?DOC(false). -spec create_repeating_mask(bitstring(), integer()) -> bitstring(). create_repeating_mask(Mask_key, Size) -> case Size of 1 -> _pipe = gleam_stdlib:bit_array_slice(Mask_key, 0, Size), gleam@result:unwrap(_pipe, <<>>); 2 -> _pipe = gleam_stdlib:bit_array_slice(Mask_key, 0, Size), gleam@result:unwrap(_pipe, <<>>); 3 -> _pipe = gleam_stdlib:bit_array_slice(Mask_key, 0, Size), gleam@result:unwrap(_pipe, <<>>); 4 -> _pipe = gleam_stdlib:bit_array_slice(Mask_key, 0, Size), gleam@result:unwrap(_pipe, <<>>); _ -> Repetitions = Size div 4, Remainder = Size rem 4, Base = begin _pipe@1 = gleam@list:repeat(Mask_key, Repetitions), gleam_stdlib:bit_array_concat(_pipe@1) end, case Remainder of 0 -> Base; N -> Partial = begin _pipe@2 = gleam_stdlib:bit_array_slice(Mask_key, 0, N), gleam@result:unwrap(_pipe@2, <<>>) end, <> end end. -file("src/ewe/internal/gramps/websocket.gleam", 79). ?DOC(false). -spec mask_data(bitstring(), list(bitstring())) -> bitstring(). mask_data(Data, Masks) -> {M1@1, M2@1, M3@1, M4@1} = case Masks of [M1, M2, M3, M4] -> {M1, M2, M3, M4}; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"ewe/internal/gramps/websocket"/utf8>>, function => <<"mask_data"/utf8>>, line => 80, value => _assert_fail, start => 2058, 'end' => 2093, pattern_start => 2069, pattern_end => 2085}) end, Mask_key = <>, Payload_size = erlang:byte_size(Data), Full_mask = create_repeating_mask(Mask_key, Payload_size), crypto:exor(Data, Full_mask). -file("src/ewe/internal/gramps/websocket.gleam", 118). ?DOC(false). -spec decode_frame( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()) ) -> {ok, {parsed_frame(), bitstring()}} | {error, frame_parse_error()}. decode_frame(Message, Context) -> case Message of <> -> Compressed@1 = Compressed =:= 1, Masked@1 = Masked =:= 1, gleam@bool:guard( Compressed@1 andalso gleam@option:is_none(Context), {error, invalid_frame}, fun() -> gleam@bool:guard( (Rsv2 =:= 1) orelse (Rsv3 =:= 1), {error, invalid_frame}, fun() -> gleam@bool:guard( begin Is_control_frame = (Opcode >= 8) andalso (Opcode =< 10), Is_fragmented = Complete =:= 0, Is_control_frame andalso Is_fragmented end, {error, invalid_frame}, fun() -> Payload_size = case Payload_length of 126 -> 16; 127 -> 64; _ -> 0 end, Maybe_pair = case {Masked@1, Rest} of {true, <>} -> Payload_byte_size = case Length of 0 -> Payload_length; N -> N end, case {erlang:byte_size(Rest@1) >= Payload_byte_size, Rest@1} of {true, <>} -> Data = mask_data( Payload, [Mask1, Mask2, Mask3, Mask4] ), {ok, {Data, Remaining}}; {_, _} -> {error, {need_more_data, Message}} end; {true, _} -> {error, {need_more_data, Message}}; {false, <>} -> Payload_byte_size@1 = case Length@1 of 0 -> Payload_length; N@1 -> N@1 end, case Rest@2 of <> -> {ok, {Payload@1, Rest@3}}; _ -> {error, {need_more_data, Message}} end; {_, _} -> {error, invalid_frame} end, gleam@result:'try'( Maybe_pair, fun(_use0) -> {Data@1, Rest@4} = _use0, _pipe = case Opcode of 0 -> {ok, {continuation, Payload_size, Data@1}}; 1 -> case Compressed@1 of true -> {ok, {data, {compressed_text_frame, Data@1}}}; false -> {ok, {data, {text_frame, Data@1}}} end; 2 -> case Compressed@1 of true -> {ok, {data, {compressed_binary_frame, Data@1}}}; false -> {ok, {data, {binary_frame, Data@1}}} end; 8 -> case Data@1 of <<>> -> {ok, {control, {close_frame, not_provided}}}; <> -> gleam@bool:guard( not gleam@bit_array:is_utf8( Rest@5 ), {error, invalid_frame}, fun() -> case Code of 1000 -> {ok, {control, {close_frame, {normal, Rest@5}}}}; 1001 -> {ok, {control, {close_frame, {going_away, Rest@5}}}}; 1002 -> {ok, {control, {close_frame, {protocol_error, Rest@5}}}}; 1003 -> {ok, {control, {close_frame, {unexpected_data_type, Rest@5}}}}; 1007 -> {ok, {control, {close_frame, {inconsistent_data_type, Rest@5}}}}; 1008 -> {ok, {control, {close_frame, {policy_violation, Rest@5}}}}; 1009 -> {ok, {control, {close_frame, {message_too_big, Rest@5}}}}; 1010 -> {ok, {control, {close_frame, {missing_extensions, Rest@5}}}}; 1011 -> {ok, {control, {close_frame, {unexpected_condition, Rest@5}}}}; Code@1 when (Code@1 >= 3000) andalso (Code@1 =< 4999) -> {ok, {control, {close_frame, {custom_close_reason, Code@1, Rest@5}}}}; _ -> {error, invalid_frame} end end ); _ -> {error, invalid_frame} end; 9 -> {ok, {control, {ping_frame, Data@1}}}; 10 -> {ok, {control, {pong_frame, Data@1}}}; _ -> {error, invalid_frame} end, gleam@result:'try'( _pipe, fun(Frame) -> case Complete of 1 -> {ok, {{complete, Frame}, Rest@4}}; 0 -> {ok, {{incomplete, Frame}, Rest@4}}; _ -> {error, invalid_frame} end end ) end ) end ) end ) end ); _ -> {error, {need_more_data, Message}} end. -file("src/ewe/internal/gramps/websocket.gleam", 378). ?DOC(false). -spec make_length(integer()) -> bitstring(). make_length(Length) -> case Length of Length@1 when Length@1 > 65535 -> <<127:7, Length@1:64/integer>>; Length@2 when Length@2 >= 126 -> <<126:7, Length@2:16/integer>>; _ -> <> end. -file("src/ewe/internal/gramps/websocket.gleam", 391). ?DOC(false). -spec make_frame( integer(), integer(), bitstring(), compression(), gleam@option:option(bitstring()) ) -> gleam@bytes_tree:bytes_tree(). make_frame(Opcode, Length, Payload, Compressed, Mask) -> Length_section = make_length(Length), Masked = case gleam@option:is_some(Mask) of true -> 1; false -> 0 end, Mask_key = gleam@option:unwrap(Mask, <<>>), Compressed@1 = case Compressed of compressed -> 1; uncompressed -> 0 end, _pipe = <<1:1, Compressed@1:1, 0:2, Opcode:4, Masked:1, Length_section/bitstring, Mask_key/bitstring, Payload/bitstring>>, gleam@bytes_tree:from_bit_array(_pipe). -file("src/ewe/internal/gramps/websocket.gleam", 425). ?DOC(false). -spec apply_mask(bitstring(), gleam@option:option(bitstring())) -> bitstring(). apply_mask(Data, Mask) -> case Mask of {some, Mask@1} -> {Mask1@1, Mask2@1, Mask3@1, Mask4@1} = case Mask@1 of <> -> {Mask1, Mask2, Mask3, Mask4}; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"ewe/internal/gramps/websocket"/utf8>>, function => <<"apply_mask"/utf8>>, line => 428, value => _assert_fail, start => 12052, 'end' => 12197, pattern_start => 12063, pattern_end => 12190}) end, mask_data(Data, [Mask1@1, Mask2@1, Mask3@1, Mask4@1]); none -> Data end. -file("src/ewe/internal/gramps/websocket.gleam", 298). ?DOC(false). -spec encode_frame(frame(), compression(), gleam@option:option(bitstring())) -> gleam@bytes_tree:bytes_tree(). encode_frame(Frame, Compressed, Mask) -> case Frame of {data, {text_frame, Payload}} -> Payload_length = erlang:byte_size(Payload), make_frame(1, Payload_length, Payload, Compressed, Mask); {data, {compressed_text_frame, Payload}} -> Payload_length = erlang:byte_size(Payload), make_frame(1, Payload_length, Payload, Compressed, Mask); {data, {binary_frame, Payload@1}} -> Payload_length@1 = erlang:byte_size(Payload@1), make_frame(2, Payload_length@1, Payload@1, Compressed, Mask); {data, {compressed_binary_frame, Payload@1}} -> Payload_length@1 = erlang:byte_size(Payload@1), make_frame(2, Payload_length@1, Payload@1, Compressed, Mask); {control, {close_frame, Reason}} -> {Payload_length@2, Payload@2} = case Reason of not_provided -> {0, <<>>}; {going_away, Body} -> Payload_size = erlang:byte_size(Body) + 2, {Payload_size, <<1001:16, Body/bitstring>>}; {inconsistent_data_type, Body@1} -> Payload_size@1 = erlang:byte_size(Body@1) + 2, {Payload_size@1, <<1007:16, Body@1/bitstring>>}; {message_too_big, Body@2} -> Payload_size@2 = erlang:byte_size(Body@2) + 2, {Payload_size@2, <<1009:16, Body@2/bitstring>>}; {missing_extensions, Body@3} -> Payload_size@3 = erlang:byte_size(Body@3) + 2, {Payload_size@3, <<1010:16, Body@3/bitstring>>}; {normal, Body@4} -> Payload_size@4 = erlang:byte_size(Body@4) + 2, {Payload_size@4, <<1000:16, Body@4/bitstring>>}; {policy_violation, Body@5} -> Payload_size@5 = erlang:byte_size(Body@5) + 2, {Payload_size@5, <<1008:16, Body@5/bitstring>>}; {protocol_error, Body@6} -> Payload_size@6 = erlang:byte_size(Body@6) + 2, {Payload_size@6, <<1002:16, Body@6/bitstring>>}; {unexpected_condition, Body@7} -> Payload_size@7 = erlang:byte_size(Body@7) + 2, {Payload_size@7, <<1011:16, Body@7/bitstring>>}; {unexpected_data_type, Body@8} -> Payload_size@8 = erlang:byte_size(Body@8) + 2, {Payload_size@8, <<1003:16, Body@8/bitstring>>}; {custom_close_reason, Code, Body@9} -> Payload_size@9 = erlang:byte_size(Body@9) + 2, Code@1 = case Code < 5000 of true -> Code; false -> 1000 end, {Payload_size@9, <>} end, make_frame( 8, Payload_length@2, apply_mask(Payload@2, Mask), Compressed, Mask ); {control, {pong_frame, Payload@3}} -> Payload_length@3 = erlang:byte_size(Payload@3), make_frame(10, Payload_length@3, Payload@3, Compressed, Mask); {control, {ping_frame, Payload@4}} -> Payload_length@4 = erlang:byte_size(Payload@4), make_frame(9, Payload_length@4, Payload@4, Compressed, Mask); {continuation, Length, Payload@5} -> make_frame(0, Length, Payload@5, Compressed, Mask) end. -file("src/ewe/internal/gramps/websocket.gleam", 274). ?DOC(false). -spec encode_close_frame(close_reason(), gleam@option:option(bitstring())) -> gleam@bytes_tree:bytes_tree(). encode_close_frame(Reason, Mask) -> encode_frame({control, {close_frame, Reason}}, uncompressed, Mask). -file("src/ewe/internal/gramps/websocket.gleam", 289). ?DOC(false). -spec encode_continuation_frame( bitstring(), integer(), gleam@option:option(bitstring()) ) -> gleam@bytes_tree:bytes_tree(). encode_continuation_frame(Data, Total_size, Mask) -> Payload = apply_mask(Data, Mask), encode_frame({continuation, Total_size, Payload}, uncompressed, Mask). -file("src/ewe/internal/gramps/websocket.gleam", 440). ?DOC(false). -spec apply_deflate( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()) ) -> bitstring(). apply_deflate(Data, Context) -> case Context of {some, Context@1} -> ewe@internal@gramps@websocket@compression:deflate(Context@1, Data); _ -> Data end. -file("src/ewe/internal/gramps/websocket.gleam", 447). ?DOC(false). -spec apply_inflate( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()) ) -> bitstring(). apply_inflate(Data, Context) -> case Context of {some, Context@1} -> ewe@internal@gramps@websocket@compression:inflate(Context@1, Data); _ -> Data end. -file("src/ewe/internal/gramps/websocket.gleam", 454). ?DOC(false). -spec to_frame( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()), gleam@option:option(bitstring()), fun((bitstring()) -> KJQ), fun((KJQ) -> frame()) ) -> gleam@bytes_tree:bytes_tree(). to_frame(Data, Context, Mask, Create_inner_frame, Create_frame) -> Frame = begin _pipe = Data, _pipe@1 = apply_deflate(_pipe, Context), _pipe@2 = apply_mask(_pipe@1, Mask), _pipe@3 = Create_inner_frame(_pipe@2), Create_frame(_pipe@3) end, Compress = case Context of {some, _} -> compressed; _ -> uncompressed end, encode_frame(Frame, Compress, Mask). -file("src/ewe/internal/gramps/websocket.gleam", 258). ?DOC(false). -spec encode_text_frame( binary(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()), gleam@option:option(bitstring()) ) -> gleam@bytes_tree:bytes_tree(). encode_text_frame(Data, Context, Mask) -> to_frame( gleam_stdlib:identity(Data), Context, Mask, fun(Field@0) -> {text_frame, Field@0} end, fun(Field@0) -> {data, Field@0} end ). -file("src/ewe/internal/gramps/websocket.gleam", 266). ?DOC(false). -spec encode_binary_frame( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()), gleam@option:option(bitstring()) ) -> gleam@bytes_tree:bytes_tree(). encode_binary_frame(Data, Context, Mask) -> to_frame( Data, Context, Mask, fun(Field@0) -> {binary_frame, Field@0} end, fun(Field@0) -> {data, Field@0} end ). -file("src/ewe/internal/gramps/websocket.gleam", 281). ?DOC(false). -spec encode_ping_frame(bitstring(), gleam@option:option(bitstring())) -> gleam@bytes_tree:bytes_tree(). encode_ping_frame(Data, Mask) -> to_frame( Data, none, Mask, fun(Field@0) -> {ping_frame, Field@0} end, fun(Field@0) -> {control, Field@0} end ). -file("src/ewe/internal/gramps/websocket.gleam", 285). ?DOC(false). -spec encode_pong_frame(bitstring(), gleam@option:option(bitstring())) -> gleam@bytes_tree:bytes_tree(). encode_pong_frame(Data, Mask) -> to_frame( Data, none, Mask, fun(Field@0) -> {pong_frame, Field@0} end, fun(Field@0) -> {control, Field@0} end ). -file("src/ewe/internal/gramps/websocket.gleam", 474). ?DOC(false). -spec decode_many_frames( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()), list(parsed_frame()) ) -> {list(parsed_frame()), bitstring()}. decode_many_frames(Data, Context, Frames) -> case decode_frame(Data, Context) of {ok, {Frame, <<>>}} -> {lists:reverse([Frame | Frames]), <<>>}; {ok, {Frame@1, Rest}} -> decode_many_frames(Rest, Context, [Frame@1 | Frames]); {error, {need_more_data, Rest@1}} -> {lists:reverse(Frames), Rest@1}; {error, invalid_frame} -> {lists:reverse(Frames), Data} end. -file("src/ewe/internal/gramps/websocket.gleam", 492). ?DOC(false). -spec decode_many_frames_result( bitstring(), gleam@option:option(ewe@internal@gramps@websocket@compression:context()), list(parsed_frame()) ) -> {ok, {list(parsed_frame()), bitstring()}} | {error, many_frames_parse_error()}. decode_many_frames_result(Data, Context, Frames) -> case decode_frame(Data, Context) of {ok, {Frame, <<>>}} -> {ok, {lists:reverse([Frame | Frames]), <<>>}}; {ok, {Frame@1, Rest}} -> decode_many_frames_result(Rest, Context, [Frame@1 | Frames]); {error, {need_more_data, Rest@1}} -> {error, {need_more_data_accumulated, lists:reverse(Frames), Rest@1}}; {error, invalid_frame} -> {error, contains_invalid_frame} end. -file("src/ewe/internal/gramps/websocket.gleam", 507). ?DOC(false). -spec aggregate_frames( list(parsed_frame()), gleam@option:option({frame(), list(bitstring())}), list(frame()), gleam@option:option(ewe@internal@gramps@websocket@compression:context()) ) -> {ok, list(frame())} | {error, nil}. aggregate_frames(Frames, Accumulated, Joined, Context) -> case {Frames, Accumulated} of {[], _} -> {ok, lists:reverse(Joined)}; {[{complete, {data, {compressed_text_frame, Data}}} | Rest], none} -> case Context of {some, Ctx} -> Decompressed = ewe@internal@gramps@websocket@compression:inflate( Ctx, Data ), case gleam@bit_array:is_utf8(Decompressed) of true -> Final_frame = {data, {text_frame, Decompressed}}, aggregate_frames( Rest, none, [Final_frame | Joined], Context ); false -> {error, nil} end; none -> {error, nil} end; {[{complete, {data, {compressed_binary_frame, Data@1}}} | Rest@1], none} -> case Context of {some, Ctx@1} -> Decompressed@1 = ewe@internal@gramps@websocket@compression:inflate( Ctx@1, Data@1 ), Final_frame@1 = {data, {binary_frame, Decompressed@1}}, aggregate_frames( Rest@1, none, [Final_frame@1 | Joined], Context ); none -> {error, nil} end; {[{complete, {data, {text_frame, Data@2}}} | Rest@2], none} -> case gleam@bit_array:is_utf8(Data@2) of true -> aggregate_frames( Rest@2, none, [{data, {text_frame, Data@2}} | Joined], Context ); false -> {error, nil} end; {[{complete, {data, {binary_frame, Data@3}}} | Rest@3], none} -> aggregate_frames( Rest@3, none, [{data, {binary_frame, Data@3}} | Joined], Context ); {[{complete, {continuation, _, _}} | _], none} -> {error, nil}; {[{complete, Frame} | Rest@4], none} -> aggregate_frames(Rest@4, none, [Frame | Joined], Context); {[{incomplete, Frame@1} | Rest@5], none} -> Initial_payload = case Frame@1 of {data, {text_frame, Payload}} -> Payload; {data, {binary_frame, Payload@1}} -> Payload@1; {data, {compressed_text_frame, Payload@2}} -> Payload@2; {data, {compressed_binary_frame, Payload@3}} -> Payload@3; {continuation, _, Payload@4} -> Payload@4; {control, _} -> <<>> end, aggregate_frames( Rest@5, {some, {Frame@1, [Initial_payload]}}, Joined, Context ); {[{complete, {continuation, _, Data@4}} | Rest@6], {some, {Initial_frame, Payloads}}} -> All_payloads = begin _pipe = [Data@4 | Payloads], lists:reverse(_pipe) end, Final_payload = gleam_stdlib:bit_array_concat(All_payloads), case Initial_frame of {data, {compressed_text_frame, _}} -> case Context of {some, Ctx@2} -> Decompressed@2 = ewe@internal@gramps@websocket@compression:inflate( Ctx@2, Final_payload ), case gleam@bit_array:is_utf8(Decompressed@2) of true -> Final_frame@2 = {data, {text_frame, Decompressed@2}}, aggregate_frames( Rest@6, none, [Final_frame@2 | Joined], Context ); false -> {error, nil} end; none -> {error, nil} end; {data, {compressed_binary_frame, _}} -> case Context of {some, Ctx@3} -> Decompressed@3 = ewe@internal@gramps@websocket@compression:inflate( Ctx@3, Final_payload ), Final_frame@3 = {data, {binary_frame, Decompressed@3}}, aggregate_frames( Rest@6, none, [Final_frame@3 | Joined], Context ); none -> {error, nil} end; {data, {text_frame, _}} -> case gleam@bit_array:is_utf8(Final_payload) of true -> Final_frame@4 = {data, {text_frame, Final_payload}}, aggregate_frames( Rest@6, none, [Final_frame@4 | Joined], Context ); false -> {error, nil} end; {data, {binary_frame, _}} -> Final_frame@5 = {data, {binary_frame, Final_payload}}, aggregate_frames( Rest@6, none, [Final_frame@5 | Joined], Context ); {control, _} -> {error, nil}; {continuation, _, _} -> {error, nil} end; {[{incomplete, {continuation, _, Data@5}} | Rest@7], {some, {Initial_frame@1, Payloads@1}}} -> aggregate_frames( Rest@7, {some, {Initial_frame@1, [Data@5 | Payloads@1]}}, Joined, Context ); {_, _} -> {error, nil} end. -file("src/ewe/internal/gramps/websocket.gleam", 643). ?DOC(false). -spec make_client_key() -> binary(). make_client_key() -> Bytes = crypto:strong_rand_bytes(16), gleam_stdlib:base64_encode(Bytes, true). -file("src/ewe/internal/gramps/websocket.gleam", 665). ?DOC(false). -spec has_deflate(list(binary())) -> boolean(). has_deflate(Extensions) -> gleam@list:any( Extensions, fun(Str) -> Str =:= <<"permessage-deflate"/utf8>> end ). -file("src/ewe/internal/gramps/websocket.gleam", 669). ?DOC(false). -spec get_context_takeovers(list(binary())) -> ewe@internal@gramps@websocket@compression:context_takeover(). get_context_takeovers(Extensions) -> No_client_context_takeover = gleam@list:any( Extensions, fun(Str) -> Str =:= <<"client_no_context_takeover"/utf8>> end ), No_server_context_takeover = gleam@list:any( Extensions, fun(Str@1) -> Str@1 =:= <<"server_no_context_takeover"/utf8>> end ), {context_takeover, No_client_context_takeover, No_server_context_takeover}. -file("src/ewe/internal/gramps/websocket.gleam", 652). ?DOC(false). -spec parse_websocket_key(binary()) -> binary(). parse_websocket_key(Key) -> _pipe = Key, _pipe@1 = gleam@string:append( _pipe, <<"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"/utf8>> ), _pipe@2 = crypto:hash(sha, _pipe@1), base64:encode(_pipe@2).