-module(pg_value). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/pg_value.gleam"). -export([bool/1, int/1, float/1, text/1, bytea/1, uuid/1, hstore/1, time/1, date/1, timestamp/1, timestamptz/2, interval/1, enum/1, json/1, array/2, nullable/2, decode/2, time_decoder/0, timestamp_decoder/0, date_decoder/0, encode/2, to_string/1]). -export_type([value/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( " PostgreSQL values, along with their encoders and decoders. Can\n" " be used by PostgreSQL client libraries written in gleam.\n" " Currently used by [pgl][1].\n" "\n" " [1]: https://github.com/stndrs/pgl\n" ). -type value() :: null | {bool, boolean()} | {int, integer()} | {float, float()} | {text, binary()} | {bytea, bitstring()} | {time, gleam@time@calendar:time_of_day()} | {date, gleam@time@calendar:date()} | {timestamp, gleam@time@timestamp:timestamp()} | {timestamptz, gleam@time@timestamp:timestamp(), gleam@time@duration:duration()} | {interval, pg_value@interval:interval()} | {array, list(value())} | {uuid, bitstring()} | {hstore, gleam@dict:dict(binary(), gleam@option:option(binary()))} | {enum, binary()} | {json, gleam@json:json()}. -file("src/pg_value.gleam", 56). ?DOC(" Returns a Bool value.\n"). -spec bool(boolean()) -> value(). bool(Bool) -> {bool, Bool}. -file("src/pg_value.gleam", 61). ?DOC(" Returns an Int value.\n"). -spec int(integer()) -> value(). int(Int) -> {int, Int}. -file("src/pg_value.gleam", 66). ?DOC(" Returns a Float value.\n"). -spec float(float()) -> value(). float(Float) -> {float, Float}. -file("src/pg_value.gleam", 71). ?DOC(" Returns a Text value.\n"). -spec text(binary()) -> value(). text(Text) -> {text, Text}. -file("src/pg_value.gleam", 76). ?DOC(" Returns a Bytea value.\n"). -spec bytea(bitstring()) -> value(). bytea(Bytea) -> {bytea, Bytea}. -file("src/pg_value.gleam", 82). ?DOC( " Returns a UUID `Value`. Callers are responsible for ensuring the provided\n" " value is a valid UUID. If the value is not a valid UUID, encoding will fail.\n" ). -spec uuid(bitstring()) -> value(). uuid(Uuid) -> {uuid, Uuid}. -file("src/pg_value.gleam", 87). ?DOC(" Returns an Hstore value. Keys map to optional string values.\n"). -spec hstore(gleam@dict:dict(binary(), gleam@option:option(binary()))) -> value(). hstore(Hstore) -> {hstore, Hstore}. -file("src/pg_value.gleam", 92). ?DOC(" Returns a Time value.\n"). -spec time(gleam@time@calendar:time_of_day()) -> value(). time(Time_of_day) -> {time, Time_of_day}. -file("src/pg_value.gleam", 97). ?DOC(" Returns a Date value.\n"). -spec date(gleam@time@calendar:date()) -> value(). date(Date) -> {date, Date}. -file("src/pg_value.gleam", 102). ?DOC(" Returns a Timestamp value.\n"). -spec timestamp(gleam@time@timestamp:timestamp()) -> value(). timestamp(Timestamp) -> {timestamp, Timestamp}. -file("src/pg_value.gleam", 107). ?DOC(" Returns a Timestamp value with a timezone offset.\n"). -spec timestamptz( gleam@time@timestamp:timestamp(), gleam@time@duration:duration() ) -> value(). timestamptz(Timestamp, Offset) -> {timestamptz, Timestamp, Offset}. -file("src/pg_value.gleam", 115). ?DOC(" Returns an Interval value.\n"). -spec interval(pg_value@interval:interval()) -> value(). interval(Interval) -> {interval, Interval}. -file("src/pg_value.gleam", 120). ?DOC(" Returns an Enum value with the given label.\n"). -spec enum(binary()) -> value(). enum(Label) -> {enum, Label}. -file("src/pg_value.gleam", 125). ?DOC(" Returns a Json value.\n"). -spec json(gleam@json:json()) -> value(). json(Json) -> {json, Json}. -file("src/pg_value.gleam", 130). ?DOC(" Returns an Array value. Each element is converted using the provided function.\n"). -spec array(list(EBB), fun((EBB) -> value())) -> value(). array(Elements, Kind) -> _pipe = Elements, _pipe@1 = gleam@list:map(_pipe, Kind), {array, _pipe@1}. -file("src/pg_value.gleam", 147). ?DOC( " Checks if the provided value is `option.Some` or `option.None`. If\n" " `None` then the value returned is `value.Null`. If `Some` value is\n" " provided then it is passed to the `inner_type` function.\n" "\n" " Example:\n" "\n" " ```gleam\n" " let int = pg_value.nullable(pg_value.int, Some(10))\n" "\n" " let null = pg_value.nullable(pg_value.int, None)\n" " ```\n" ). -spec nullable(fun((EBD) -> value()), gleam@option:option(EBD)) -> value(). nullable(Inner_type, Optional) -> case Optional of {some, Term} -> Inner_type(Term); none -> null end. -file("src/pg_value.gleam", 197). -spec escape(binary()) -> binary(). escape(Str) -> _pipe = Str, _pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>), _pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>), gleam@string:replace(_pipe@2, <<"'"/utf8>>, <<"''"/utf8>>). -file("src/pg_value.gleam", 208). -spec do_uuid_to_string(bitstring(), integer(), binary(), binary()) -> binary(). do_uuid_to_string(Uuid, Position, Acc, Separator) -> case Position of 8 -> do_uuid_to_string( Uuid, Position + 1, <>, Separator ); 13 -> do_uuid_to_string( Uuid, Position + 1, <>, Separator ); 18 -> do_uuid_to_string( Uuid, Position + 1, <>, Separator ); 23 -> do_uuid_to_string( Uuid, Position + 1, <>, Separator ); _ -> case Uuid of <> -> String = begin _pipe = gleam@int:to_base16(I), string:lowercase(_pipe) end, do_uuid_to_string( Rest, Position + 1, <>, Separator ); _ -> Acc end end. -file("src/pg_value.gleam", 204). -spec uuid_to_string(bitstring()) -> binary(). uuid_to_string(Uuid) -> do_uuid_to_string(Uuid, 0, <<""/utf8>>, <<"-"/utf8>>). -file("src/pg_value.gleam", 250). -spec bool_to_string(boolean()) -> binary(). bool_to_string(Bool) -> case Bool of true -> <<"TRUE"/utf8>>; false -> <<"FALSE"/utf8>> end. -file("src/pg_value.gleam", 306). -spec negate_duration(gleam@time@duration:duration()) -> gleam@time@duration:duration(). negate_duration(D) -> gleam@time@duration:difference(D, gleam@time@duration:seconds(0)). -file("src/pg_value.gleam", 310). -spec single_quote(binary()) -> binary(). single_quote(Value) -> <<<<"'"/utf8, Value/binary>>/binary, "'"/utf8>>. -file("src/pg_value.gleam", 179). -spec hstore_to_string(gleam@dict:dict(binary(), gleam@option:option(binary()))) -> binary(). hstore_to_string(Hstore) -> _pipe = Hstore, _pipe@1 = maps:to_list(_pipe), _pipe@2 = gleam@list:map( _pipe@1, fun(Key_val) -> {Key, Val} = Key_val, Key@1 = <<<<"\""/utf8, (escape(Key))/binary>>/binary, "\""/utf8>>, Val@2 = case Val of {some, Val@1} -> <<<<"\""/utf8, (escape(Val@1))/binary>>/binary, "\""/utf8>>; none -> <<"NULL"/utf8>> end, <<<"/utf8>>/binary, Val@2/binary>> end ), _pipe@3 = gleam@string:join(_pipe@2, <<", "/utf8>>), single_quote(_pipe@3). -file("src/pg_value.gleam", 228). -spec text_to_string(binary()) -> binary(). text_to_string(Text) -> Val = gleam@string:replace(Text, <<"'"/utf8>>, <<"''"/utf8>>), single_quote(Val). -file("src/pg_value.gleam", 258). -spec bytea_to_string(bitstring()) -> binary(). bytea_to_string(Bytea) -> Val = <<"\\x"/utf8, (gleam_stdlib:base16_encode(Bytea))/binary>>, single_quote(Val). -file("src/pg_value.gleam", 292). -spec timestamp_to_string(gleam@time@timestamp:timestamp()) -> binary(). timestamp_to_string(Timestamp) -> _pipe = gleam@time@timestamp:to_rfc3339(Timestamp, {duration, 0, 0}), single_quote(_pipe). -file("src/pg_value.gleam", 297). -spec timestamptz_to_string( gleam@time@timestamp:timestamp(), gleam@time@duration:duration() ) -> binary(). timestamptz_to_string(Timestamp, Offset) -> _pipe = negate_duration(Offset), _pipe@1 = gleam@time@timestamp:add(Timestamp, _pipe), timestamp_to_string(_pipe@1). -file("src/pg_value.gleam", 314). -spec pad_zero(integer()) -> binary(). pad_zero(N) -> case N < 10 of true -> <<"0"/utf8, (erlang:integer_to_binary(N))/binary>>; false -> erlang:integer_to_binary(N) end. -file("src/pg_value.gleam", 264). -spec date_to_string(gleam@time@calendar:date()) -> binary(). date_to_string(Date) -> Year = erlang:integer_to_binary(erlang:element(2, Date)), Month = begin _pipe = gleam@time@calendar:month_to_int(erlang:element(3, Date)), pad_zero(_pipe) end, Day = pad_zero(erlang:element(4, Date)), Date@1 = <<<<<<<>/binary, Month/binary>>/binary, "-"/utf8>>/binary, Day/binary>>, single_quote(Date@1). -file("src/pg_value.gleam", 274). -spec time_to_string(gleam@time@calendar:time_of_day()) -> binary(). time_to_string(Time_of_day) -> Hours = pad_zero(erlang:element(2, Time_of_day)), Minutes = pad_zero(erlang:element(3, Time_of_day)), Seconds = pad_zero(erlang:element(4, Time_of_day)), Milliseconds = erlang:element(5, Time_of_day) div 1000000, Msecs = case Milliseconds < 100 of true when Milliseconds =:= 0 -> <<""/utf8>>; true when Milliseconds < 10 -> <<".00"/utf8, (erlang:integer_to_binary(Milliseconds))/binary>>; true -> <<".0"/utf8, (erlang:integer_to_binary(Milliseconds))/binary>>; false -> <<"."/utf8, (erlang:integer_to_binary(Milliseconds))/binary>> end, Time = <<<<<<<<<>/binary, Minutes/binary>>/binary, ":"/utf8>>/binary, Seconds/binary>>/binary, Msecs/binary>>, single_quote(Time). -file("src/pg_value.gleam", 383). -spec validate_typesend( binary(), pg_value@type_info:type_info(), fun(() -> {ok, EBO} | {error, binary()}) ) -> {ok, EBO} | {error, binary()}. validate_typesend(Expected, Info, Next) -> gleam@bool:lazy_guard( Expected =:= erlang:element(4, Info), Next, fun() -> {error, <<<<<<"Attempted to encode "/utf8, Expected/binary>>/binary, " as "/utf8>>/binary, (erlang:element(4, Info))/binary>>} end ). -file("src/pg_value.gleam", 393). -spec encode_uuid(bitstring(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_uuid(Uuid, Info) -> validate_typesend(<<"uuid_send"/utf8>>, Info, fun() -> case Uuid of <> -> {ok, <<16:32/big-integer, Uuid@1:128/big-integer>>}; _ -> {error, <<"Invalid UUID"/utf8>>} end end). -file("src/pg_value.gleam", 419). -spec do_encode_hstore(gleam@dict:dict(binary(), gleam@option:option(binary()))) -> {ok, bitstring()} | {error, binary()}. do_encode_hstore(Hstore) -> Encoded = begin _pipe = Hstore, _pipe@1 = maps:to_list(_pipe), gleam@list:fold( _pipe@1, <<>>, fun(Acc, Key_val) -> Encoded_key = begin _pipe@2 = erlang:element(1, Key_val), gleam_stdlib:identity(_pipe@2) end, Key_size = erlang:byte_size(Encoded_key), Encoded_value = case erlang:element(2, Key_val) of {some, Val} -> Encoded_val = gleam_stdlib:identity(Val), Val_size = erlang:byte_size(Encoded_val), <>; none -> <<-1:32/big-integer>> end, _pipe@3 = Acc, _pipe@4 = gleam@bit_array:append( _pipe@3, <> ), gleam@bit_array:append(_pipe@4, Encoded_value) end ) end, Size = maps:size(Hstore), {ok, <>}. -file("src/pg_value.gleam", 406). -spec encode_hstore( gleam@dict:dict(binary(), gleam@option:option(binary())), pg_value@type_info:type_info() ) -> {ok, bitstring()} | {error, binary()}. encode_hstore(Hstore, Info) -> validate_typesend( <<"hstore_send"/utf8>>, Info, fun() -> gleam@result:map( do_encode_hstore(Hstore), fun(Encoded) -> Size = erlang:byte_size(Encoded), <> end ) end ). -file("src/pg_value.gleam", 474). -spec arr_dims(list(value())) -> list(integer()). arr_dims(Elems) -> case Elems of [] -> []; [{array, Inner} | _] -> Inner_dims = arr_dims(Inner), Dim = erlang:length(Elems), [Dim | Inner_dims]; Elems@1 -> Dim@1 = erlang:length(Elems@1), [Dim@1] end. -file("src/pg_value.gleam", 509). -spec array_header(list(integer()), boolean(), integer()) -> bitstring(). array_header(Dimensions, Has_nulls, Elem_type_oid) -> Num_dims = erlang:length(Dimensions), Flags = case Has_nulls of true -> 1; false -> 0 end, Encoded_dimensions = begin _pipe = Dimensions, _pipe@1 = gleam@list:map( _pipe, fun(Dim) -> <> end ), gleam_stdlib:bit_array_concat(_pipe@1) end, _pipe@2 = [<>, Encoded_dimensions], gleam_stdlib:bit_array_concat(_pipe@2). -file("src/pg_value.gleam", 489). -spec do_encode_array( list(integer()), boolean(), pg_value@type_info:type_info(), list(bitstring()) ) -> {ok, bitstring()} | {error, binary()}. do_encode_array(Dimensions, Has_nulls, Info, Encoded) -> Header = array_header(Dimensions, Has_nulls, erlang:element(2, Info)), Encoder = fun(Bits) -> Len = erlang:byte_size(Bits), {ok, <>} end, case Encoded of [] -> Encoder(Header); _ -> _pipe = gleam_stdlib:bit_array_concat([Header | Encoded]), Encoder(_pipe) end. -file("src/pg_value.gleam", 533). -spec encode_null() -> {ok, bitstring()} | {error, binary()}. encode_null() -> {ok, <<-1:32/big-integer>>}. -file("src/pg_value.gleam", 537). -spec encode_bool(boolean(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_bool(Bool, Info) -> validate_typesend(<<"boolsend"/utf8>>, Info, fun() -> case Bool of true -> {ok, <<1:32/big-integer, 1:8/big-integer>>}; false -> {ok, <<1:32/big-integer, 0:8/big-integer>>} end end). -file("src/pg_value.gleam", 608). -spec encode_float4(float(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_float4(Num, Info) -> validate_typesend( <<"float4send"/utf8>>, Info, fun() -> {ok, <<4:32/big-integer, Num:32/big-float>>} end ). -file("src/pg_value.gleam", 617). -spec encode_float8(float(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_float8(Num, Info) -> validate_typesend( <<"float8send"/utf8>>, Info, fun() -> {ok, <<8:32/big-integer, Num:64/big-float>>} end ). -file("src/pg_value.gleam", 597). -spec encode_float(float(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_float(Num, Info) -> case erlang:element(4, Info) of <<"float4send"/utf8>> -> encode_float4(Num, Info); <<"float8send"/utf8>> -> encode_float8(Num, Info); _ -> {error, <<"Unsupported float type"/utf8>>} end. -file("src/pg_value.gleam", 626). -spec encode_text(binary(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_text(Text, Info) -> Encoder = fun(Text@1) -> Bits = gleam_stdlib:identity(Text@1), Len = erlang:byte_size(Bits), {ok, <>} end, case erlang:element(4, Info) of <<"varcharsend"/utf8>> -> Encoder(Text); <<"textsend"/utf8>> -> Encoder(Text); <<"charsend"/utf8>> -> Encoder(Text); <<"namesend"/utf8>> -> Encoder(Text); _ -> {error, <<<<<<"Attempted to encode '"/utf8, Text/binary>>/binary, "' as "/utf8>>/binary, (erlang:element(4, Info))/binary>>} end. -file("src/pg_value.gleam", 646). -spec encode_enum(binary(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_enum(Label, Info) -> validate_typesend( <<"enum_send"/utf8>>, Info, fun() -> Bits = gleam_stdlib:identity(Label), Len = erlang:byte_size(Bits), {ok, <>} end ). -file("src/pg_value.gleam", 658). -spec encode_json(gleam@json:json(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_json(Json_val, Info) -> Json_string = gleam@json:to_string(Json_val), Json_bits = gleam_stdlib:identity(Json_string), case erlang:element(4, Info) of <<"json_send"/utf8>> -> Len = erlang:byte_size(Json_bits), {ok, <>}; <<"jsonb_send"/utf8>> -> Len@1 = erlang:byte_size(Json_bits) + 1, {ok, <>}; _ -> {error, <<"Attempted to encode json as "/utf8, (erlang:element(4, Info))/binary>>} end. -file("src/pg_value.gleam", 678). -spec encode_bytea(bitstring(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_bytea(Bits, Info) -> validate_typesend( <<"byteasend"/utf8>>, Info, fun() -> Len = erlang:byte_size(Bits), {ok, <>} end ). -file("src/pg_value.gleam", 838). -spec do_decode_array(integer(), bitstring(), list({integer(), integer()})) -> {ok, {bitstring(), list({integer(), integer()})}} | {error, binary()}. do_decode_array(Count, Bits, Acc) -> case Count of 0 -> {ok, {Bits, Acc}}; Idx -> case Bits of <> -> Current = {Nbr, L_bound}, Data_info1 = gleam@list:prepend(Acc, Current), do_decode_array((Idx - 1), Rest1, Data_info1); _ -> {error, <<"invalid array"/utf8>>} end end. -file("src/pg_value.gleam", 864). -spec decode_array_elems( bitstring(), fun((bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}), list(gleam@dynamic:dynamic_()) ) -> {ok, list(gleam@dynamic:dynamic_())} | {error, binary()}. decode_array_elems(Bits, Decoder, Acc) -> case Bits of <<>> -> {ok, lists:reverse(Acc)}; <<-1:32/big-signed-integer, Rest/bitstring>> -> _pipe = gleam@list:prepend(Acc, gleam@dynamic:nil()), decode_array_elems(Rest, Decoder, _pipe); <> -> Elem_len = Size * 8, case Rest@1 of <> -> gleam@result:'try'( Decoder(Val_bin), fun(Decoded) -> _pipe@1 = gleam@list:prepend(Acc, Decoded), decode_array_elems(Rest1, Decoder, _pipe@1) end ); _ -> {error, <<"invalid array"/utf8>>} end; _ -> {error, <<"invalid array"/utf8>>} end. -file("src/pg_value.gleam", 818). -spec decode_array( bitstring(), fun((bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_array(Bits, Decoder) -> case Bits of <> -> gleam@result:'try'( do_decode_array(Dimensions, Rest, []), fun(Data) -> _pipe = decode_array_elems( erlang:element(1, Data), Decoder, [] ), gleam@result:map(_pipe, fun erlang:list_to_tuple/1) end ); _ -> {error, <<"invalid array"/utf8>>} end. -file("src/pg_value.gleam", 892). -spec decode_bool(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_bool(Bits) -> case Bits of <<1:8/big-signed-integer>> -> {ok, gleam_stdlib:identity(true)}; <<0:8/big-signed-integer>> -> {ok, gleam_stdlib:identity(false)}; _ -> {error, <<"invalid bool"/utf8>>} end. -file("src/pg_value.gleam", 900). -spec decode_int2(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_int2(Bits) -> case Bits of <> -> {ok, gleam_stdlib:identity(Num)}; _ -> {error, <<"invalid int2"/utf8>>} end. -file("src/pg_value.gleam", 907). -spec decode_oid(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_oid(Bits) -> case Bits of <> -> {ok, gleam_stdlib:identity(Num)}; _ -> {error, <<"invalid oid"/utf8>>} end. -file("src/pg_value.gleam", 915). -spec decode_int4(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_int4(Bits) -> case Bits of <> -> {ok, gleam_stdlib:identity(Num)}; _ -> {error, <<"invalid int4"/utf8>>} end. -file("src/pg_value.gleam", 922). -spec decode_int8(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_int8(Bits) -> case Bits of <> -> {ok, gleam_stdlib:identity(Num)}; _ -> {error, <<"invalid int8"/utf8>>} end. -file("src/pg_value.gleam", 929). -spec decode_float4(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_float4(Bits) -> case Bits of <> -> _pipe = Value, _pipe@1 = gleam_stdlib:identity(_pipe), {ok, _pipe@1}; _ -> {error, <<"invalid float4"/utf8>>} end. -file("src/pg_value.gleam", 940). -spec decode_float8(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_float8(Bits) -> case Bits of <> -> _pipe = Value, _pipe@1 = gleam_stdlib:identity(_pipe), {ok, _pipe@1}; _ -> {error, <<"invalid float8"/utf8>>} end. -file("src/pg_value.gleam", 951). -spec decode_varchar(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_varchar(Bits) -> _pipe = gleam@bit_array:to_string(Bits), _pipe@1 = gleam@result:map(_pipe, fun gleam_stdlib:identity/1), gleam@result:replace_error(_pipe@1, <<"invalid varchar"/utf8>>). -file("src/pg_value.gleam", 957). -spec decode_text(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_text(Bits) -> _pipe = gleam@bit_array:to_string(Bits), _pipe@1 = gleam@result:map(_pipe, fun gleam_stdlib:identity/1), gleam@result:replace_error(_pipe@1, <<"invalid text"/utf8>>). -file("src/pg_value.gleam", 963). -spec decode_enum(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_enum(Bits) -> _pipe = gleam@bit_array:to_string(Bits), _pipe@1 = gleam@result:map(_pipe, fun gleam_stdlib:identity/1), gleam@result:replace_error(_pipe@1, <<"invalid enum"/utf8>>). -file("src/pg_value.gleam", 969). -spec decode_json(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_json(Bits) -> _pipe = gleam@bit_array:to_string(Bits), _pipe@1 = gleam@result:map(_pipe, fun gleam_stdlib:identity/1), gleam@result:replace_error(_pipe@1, <<"invalid json"/utf8>>). -file("src/pg_value.gleam", 975). -spec decode_jsonb(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_jsonb(Bits) -> case Bits of <<1:8/integer, Rest/bitstring>> -> _pipe = gleam@bit_array:to_string(Rest), _pipe@1 = gleam@result:map(_pipe, fun gleam_stdlib:identity/1), gleam@result:replace_error(_pipe@1, <<"invalid jsonb"/utf8>>); _ -> {error, <<"invalid jsonb"/utf8>>} end. -file("src/pg_value.gleam", 985). -spec decode_bytea(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_bytea(Bits) -> {ok, gleam_stdlib:identity(Bits)}. -file("src/pg_value.gleam", 989). -spec decode_uuid(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_uuid(Bits) -> case Bits of <<_:128/big-integer>> -> {ok, gleam_stdlib:identity(Bits)}; _ -> {error, <<"invalid uuid"/utf8>>} end. -file("src/pg_value.gleam", 1038). -spec decode_hstore_key(bitstring()) -> {ok, {binary(), bitstring()}} | {error, nil}. decode_hstore_key(Bits) -> case Bits of <> -> gleam@result:map( gleam@bit_array:to_string(Key), fun(Key@1) -> {Key@1, Rest} end ); _ -> {error, nil} end. -file("src/pg_value.gleam", 1049). -spec decode_hstore_value(bitstring()) -> {ok, {gleam@option:option(binary()), bitstring()}} | {error, nil}. decode_hstore_value(Bits) -> case Bits of <<-1:32/big-signed-integer, Rest/bitstring>> -> {ok, {none, Rest}}; <> -> gleam@result:map( gleam@bit_array:to_string(Val), fun(Val@1) -> {{some, Val@1}, Rest@1} end ); _ -> {error, nil} end. -file("src/pg_value.gleam", 1020). -spec do_decode_hstore( integer(), bitstring(), gleam@dict:dict(binary(), gleam@option:option(binary())) ) -> {ok, gleam@dict:dict(binary(), gleam@option:option(binary()))} | {error, nil}. do_decode_hstore(Size, Bits, Acc) -> case {Size, Bits} of {0, <<>>} -> {ok, Acc}; {Size@1, Bits1} -> gleam@result:'try'( decode_hstore_key(Bits1), fun(_use0) -> {Key, Rest} = _use0, gleam@result:'try'( decode_hstore_value(Rest), fun(_use0@1) -> {Val, Rest1} = _use0@1, Acc@1 = begin _pipe = Acc, gleam@dict:insert(_pipe, Key, Val) end, do_decode_hstore(Size@1 - 1, Rest1, Acc@1) end ) end ) end. -file("src/pg_value.gleam", 996). -spec decode_hstore(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_hstore(Bits) -> case Bits of <> -> _pipe = do_decode_hstore(Size, Rest, maps:new()), _pipe@4 = gleam@result:map(_pipe, fun(Hstore) -> _pipe@1 = Hstore, _pipe@2 = maps:to_list(_pipe@1), _pipe@3 = gleam@list:map( _pipe@2, fun(Key_val) -> Key = gleam_stdlib:identity( erlang:element(1, Key_val) ), Val@1 = case erlang:element(2, Key_val) of {some, Val} -> gleam_stdlib:identity(Val); none -> gleam@dynamic:nil() end, {Key, Val@1} end ), gleam@dynamic:properties(_pipe@3) end), gleam@result:replace_error(_pipe@4, <<"invalid hstore"/utf8>>); _ -> {error, <<"invalid hstore"/utf8>>} end. -file("src/pg_value.gleam", 1128). -spec decode_interval(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_interval(Bits) -> case Bits of <> -> _pipe = erlang:list_to_tuple( [gleam_stdlib:identity(Months), gleam_stdlib:identity(Days), gleam_stdlib:identity(Microseconds)] ), {ok, _pipe}; _ -> {error, <<"invalid interval"/utf8>>} end. -file("src/pg_value.gleam", 546). -spec encode_oid(integer(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_oid(Num, Info) -> validate_typesend( <<"oidsend"/utf8>>, Info, fun() -> case (0 =< Num) andalso (Num =< 16#FFFFFFFF) of true -> {ok, <<4:32/big-integer, Num:32/big-integer>>}; false -> {error, <<"Out of range for oid"/utf8>>} end end ). -file("src/pg_value.gleam", 570). -spec encode_int2(integer(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_int2(Num, Info) -> validate_typesend( <<"int2send"/utf8>>, Info, fun() -> case (- 16#8000 =< Num) andalso (Num =< 16#7FFF) of true -> {ok, <<2:32/big-integer, Num:16/big-integer>>}; false -> {error, <<"Out of range for int2"/utf8>>} end end ). -file("src/pg_value.gleam", 579). -spec encode_int4(integer(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_int4(Num, Info) -> validate_typesend( <<"int4send"/utf8>>, Info, fun() -> case (- 16#80000000 =< Num) andalso (Num =< 16#7FFFFFFF) of true -> {ok, <<4:32/big-integer, Num:32/big-integer>>}; false -> {error, <<"Out of range for int4"/utf8>>} end end ). -file("src/pg_value.gleam", 588). -spec encode_int8(integer(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_int8(Num, Info) -> validate_typesend( <<"int8send"/utf8>>, Info, fun() -> case (- 16#8000000000000000 =< Num) andalso (Num =< 16#7FFFFFFFFFFFFFFF) of true -> {ok, <<8:32/big-integer, Num:64/big-integer>>}; false -> {error, <<"Out of range for int8"/utf8>>} end end ). -file("src/pg_value.gleam", 555). -spec encode_int(integer(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_int(Num, Info) -> case erlang:element(4, Info) of <<"oidsend"/utf8>> -> encode_oid(Num, Info); <<"int2send"/utf8>> -> encode_int2(Num, Info); <<"int4send"/utf8>> -> encode_int4(Num, Info); <<"int8send"/utf8>> -> encode_int8(Num, Info); _ -> Message = <<<<<<"Attempted to encode "/utf8, (erlang:integer_to_binary(Num))/binary>>/binary, " as "/utf8>>/binary, (erlang:element(4, Info))/binary>>, {error, Message} end. -file("src/pg_value.gleam", 1096). -spec handle_timestamp(integer()) -> gleam@dynamic:dynamic_(). handle_timestamp(Microseconds) -> Seconds_since_unix_epoch = begin _pipe = (Microseconds div 1000000), _pipe@1 = gleam@int:add(_pipe, 63113904000), gleam@int:subtract(_pipe@1, 62167219200) end, Usecs_since_unix_epoch = Seconds_since_unix_epoch * 1000000, _pipe@2 = Usecs_since_unix_epoch, _pipe@3 = gleam@int:add(_pipe@2, (Microseconds rem 1000000)), gleam_stdlib:identity(_pipe@3). -file("src/pg_value.gleam", 1080). -spec decode_timestamp(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_timestamp(Bits) -> Pos_infinity = 16#7FFFFFFFFFFFFFFF, Neg_infinity = - 16#8000000000000000, case Bits of <> -> case Num of _ when Num =:= Pos_infinity -> {ok, gleam_stdlib:identity(<<"infinity"/utf8>>)}; _ when Num =:= Neg_infinity -> {ok, gleam_stdlib:identity(<<"-infinity"/utf8>>)}; _ -> {ok, handle_timestamp(Num)} end; _ -> {error, <<"invalid timestamp"/utf8>>} end. -file("src/pg_value.gleam", 1171). -spec unix_seconds_before_postgres_epoch() -> gleam@time@duration:duration(). unix_seconds_before_postgres_epoch() -> _pipe = 62167219200, _pipe@1 = gleam@int:subtract(_pipe, 63113904000), gleam@time@duration:seconds(_pipe@1). -file("src/pg_value.gleam", 689). -spec encode_date(gleam@time@calendar:date(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_date(Date, Info) -> validate_typesend( <<"date_send"/utf8>>, Info, fun() -> Gregorian_days = calendar:date_to_gregorian_days( erlang:element(2, Date), gleam@time@calendar:month_to_int(erlang:element(3, Date)), erlang:element(4, Date) ), Pg_days = Gregorian_days - 730485, {ok, <<4:32/big-integer, Pg_days:32/big-integer>>} end ). -file("src/pg_value.gleam", 1155). -spec days_to_date(integer()) -> {ok, gleam@time@calendar:date()} | {error, nil}. days_to_date(Days) -> {Year, Month, Day} = calendar:gregorian_days_to_date(Days + 730485), _pipe = gleam@time@calendar:month_from_int(Month), gleam@result:map(_pipe, fun(Month@1) -> {date, Year, Month@1, Day} end). -file("src/pg_value.gleam", 1109). -spec decode_date(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_date(Bits) -> case Bits of <> -> _pipe = days_to_date(Days), _pipe@1 = gleam@result:map( _pipe, fun(Date) -> Month = gleam@time@calendar:month_to_int( erlang:element(3, Date) ), erlang:list_to_tuple( [gleam_stdlib:identity(erlang:element(2, Date)), gleam_stdlib:identity(Month), gleam_stdlib:identity(erlang:element(4, Date))] ) end ), gleam@result:replace_error(_pipe@1, <<"Invalid month"/utf8>>); _ -> {error, <<"invalid date"/utf8>>} end. -file("src/pg_value.gleam", 722). -spec encode_interval( pg_value@interval:interval(), pg_value@type_info:type_info() ) -> {ok, bitstring()} | {error, binary()}. encode_interval(Interval, Info) -> validate_typesend( <<"interval_send"/utf8>>, Info, fun() -> {interval, Months, Days, Seconds, Microseconds} = Interval, Usecs = (Seconds * 1000000) + Microseconds, Encoded = <<16:32/big-integer, Usecs:64/big-integer, Days:32/big-integer, Months:32/big-integer>>, {ok, Encoded} end ). -file("src/pg_value.gleam", 1146). -spec from_microseconds(integer()) -> gleam@time@calendar:time_of_day(). from_microseconds(Usecs) -> Seconds = case 1000000 of 0 -> 0; Gleam@denominator -> Usecs div Gleam@denominator end, Nanoseconds = (case 1000000 of 0 -> 0; Gleam@denominator@1 -> Usecs rem Gleam@denominator@1 end) * 1000, {Hours, Minutes, Seconds@1} = calendar:seconds_to_time(Seconds), {time_of_day, Hours, Minutes, Seconds@1, Nanoseconds}. -file("src/pg_value.gleam", 1063). -spec decode_time(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode_time(Bits) -> case Bits of <> -> Tod = from_microseconds(Microseconds), _pipe = erlang:list_to_tuple( [gleam_stdlib:identity(erlang:element(2, Tod)), gleam_stdlib:identity(erlang:element(3, Tod)), gleam_stdlib:identity(erlang:element(4, Tod)), gleam_stdlib:identity(erlang:element(5, Tod) div 1000)] ), {ok, _pipe}; _ -> {error, <<"invalid time"/utf8>>} end. -file("src/pg_value.gleam", 780). ?DOC( " Decodes binary PostgreSQL data into a Dynamic value. Dynamic values\n" " can then be decoded using [gleam/dynamic/decode][1].\n" "\n" " [1]: https://hexdocs.pm/gleam_stdlib/gleam/dynamic/decode.html\n" ). -spec decode(bitstring(), pg_value@type_info:type_info()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. decode(Bits, Info) -> case erlang:element(5, Info) of <<"array_recv"/utf8>> -> decode_array(Bits, fun(Elem) -> case erlang:element(10, Info) of {some, Elem_ti} -> decode(Elem, Elem_ti); none -> {error, <<"elem type missing"/utf8>>} end end); <<"boolrecv"/utf8>> -> decode_bool(Bits); <<"oidrecv"/utf8>> -> decode_oid(Bits); <<"int2recv"/utf8>> -> decode_int2(Bits); <<"int4recv"/utf8>> -> decode_int4(Bits); <<"int8recv"/utf8>> -> decode_int8(Bits); <<"float4recv"/utf8>> -> decode_float4(Bits); <<"float8recv"/utf8>> -> decode_float8(Bits); <<"textrecv"/utf8>> -> decode_text(Bits); <<"varcharrecv"/utf8>> -> decode_varchar(Bits); <<"namerecv"/utf8>> -> decode_text(Bits); <<"charrecv"/utf8>> -> decode_text(Bits); <<"bytearecv"/utf8>> -> decode_bytea(Bits); <<"uuid_recv"/utf8>> -> decode_uuid(Bits); <<"hstore_recv"/utf8>> -> decode_hstore(Bits); <<"time_recv"/utf8>> -> decode_time(Bits); <<"date_recv"/utf8>> -> decode_date(Bits); <<"timestamp_recv"/utf8>> -> decode_timestamp(Bits); <<"timestamptz_recv"/utf8>> -> decode_timestamp(Bits); <<"interval_recv"/utf8>> -> decode_interval(Bits); <<"enum_recv"/utf8>> -> decode_enum(Bits); <<"json_recv"/utf8>> -> decode_json(Bits); <<"jsonb_recv"/utf8>> -> decode_jsonb(Bits); _ -> {error, <<"Unsupported type"/utf8>>} end. -file("src/pg_value.gleam", 322). ?DOC(" Returns a decoder for `TimeOfDay` values.\n"). -spec time_decoder() -> gleam@dynamic@decode:decoder(gleam@time@calendar:time_of_day()). time_decoder() -> gleam@dynamic@decode:field( 0, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Hours) -> gleam@dynamic@decode:field( 1, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Minutes) -> gleam@dynamic@decode:field( 2, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Seconds) -> gleam@dynamic@decode:field( 3, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Microseconds) -> Nanoseconds = Microseconds * 1000, _pipe = {time_of_day, Hours, Minutes, Seconds, Nanoseconds}, gleam@dynamic@decode:success(_pipe) end ) end ) end ) end ). -file("src/pg_value.gleam", 335). ?DOC(" Returns a decoder for `Timestamp` values.\n"). -spec timestamp_decoder() -> gleam@dynamic@decode:decoder(gleam@time@timestamp:timestamp()). timestamp_decoder() -> gleam@dynamic@decode:map( {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Microseconds) -> Seconds = Microseconds div 1000000, Nanoseconds = (Microseconds rem 1000000) * 1000, gleam@time@timestamp:from_unix_seconds_and_nanoseconds( Seconds, Nanoseconds ) end ). -file("src/pg_value.gleam", 343). ?DOC(" Returns a decoder for `Date` values.\n"). -spec date_decoder() -> gleam@dynamic@decode:decoder(gleam@time@calendar:date()). date_decoder() -> gleam@dynamic@decode:field( 0, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Year) -> gleam@dynamic@decode:field( 1, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Month) -> gleam@dynamic@decode:field( 2, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Day) -> case gleam@time@calendar:month_from_int(Month) of {ok, Month@1} -> _pipe = {date, Year, Month@1, Day}, gleam@dynamic@decode:success(_pipe); _ -> _pipe@1 = {date, 0, january, 1}, gleam@dynamic@decode:failure( _pipe@1, <<"Date"/utf8>> ) end end ) end ) end ). -file("src/pg_value.gleam", 1162). -spec to_microseconds(EGS, fun((EGS) -> {integer(), integer()})) -> integer(). to_microseconds(Kind, To_seconds_and_nanoseconds) -> {Seconds, Nanoseconds} = To_seconds_and_nanoseconds(Kind), (Seconds * 1000000) + (case 1000 of 0 -> 0; Gleam@denominator -> Nanoseconds div Gleam@denominator end). -file("src/pg_value.gleam", 706). -spec encode_time( gleam@time@calendar:time_of_day(), pg_value@type_info:type_info() ) -> {ok, bitstring()} | {error, binary()}. encode_time(Time_of_day, Info) -> validate_typesend( <<"time_send"/utf8>>, Info, fun() -> Usecs = begin _pipe = gleam@time@duration:hours( erlang:element(2, Time_of_day) ), _pipe@1 = gleam@time@duration:add( _pipe, gleam@time@duration:minutes(erlang:element(3, Time_of_day)) ), _pipe@2 = gleam@time@duration:add( _pipe@1, gleam@time@duration:seconds(erlang:element(4, Time_of_day)) ), _pipe@3 = gleam@time@duration:add( _pipe@2, gleam@time@duration:nanoseconds( erlang:element(5, Time_of_day) ) ), to_microseconds( _pipe@3, fun gleam@time@duration:to_seconds_and_nanoseconds/1 ) end, {ok, <<8:32/big-integer, Usecs:64/big-integer>>} end ). -file("src/pg_value.gleam", 742). -spec encode_timestamp( gleam@time@timestamp:timestamp(), pg_value@type_info:type_info() ) -> {ok, bitstring()} | {error, binary()}. encode_timestamp(Timestamp, Info) -> validate_typesend( <<"timestamp_send"/utf8>>, Info, fun() -> Timestamp_int = begin _pipe = unix_seconds_before_postgres_epoch(), _pipe@1 = gleam@time@timestamp:add(Timestamp, _pipe), to_microseconds( _pipe@1, fun gleam@time@timestamp:to_unix_seconds_and_nanoseconds/1 ) end, {ok, <<8:32/big-integer, Timestamp_int:64/big-integer>>} end ). -file("src/pg_value.gleam", 756). -spec encode_timestamptz( gleam@time@timestamp:timestamp(), gleam@time@duration:duration(), pg_value@type_info:type_info() ) -> {ok, bitstring()} | {error, binary()}. encode_timestamptz(Timestamp, Offset, Info) -> validate_typesend( <<"timestamptz_send"/utf8>>, Info, fun() -> Negated_offset = negate_duration(Offset), Timestamp_int = begin _pipe = unix_seconds_before_postgres_epoch(), _pipe@1 = gleam@time@duration:add(_pipe, Negated_offset), _pipe@2 = gleam@time@timestamp:add(Timestamp, _pipe@1), to_microseconds( _pipe@2, fun gleam@time@timestamp:to_unix_seconds_and_nanoseconds/1 ) end, {ok, <<8:32/big-integer, Timestamp_int:64/big-integer>>} end ). -file("src/pg_value.gleam", 452). -spec encode_array(list(value()), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode_array(Elems, Info) -> validate_typesend( <<"array_send"/utf8>>, Info, fun() -> Dimensions = arr_dims(Elems), case erlang:element(10, Info) of {some, Elem_ti} -> _pipe = Elems, _pipe@1 = gleam@list:try_map( _pipe, fun(_capture) -> encode(_capture, Elem_ti) end ), gleam@result:'try'( _pipe@1, fun(Encoded_elems) -> Has_nulls = gleam@list:contains( Encoded_elems, <<-1:32/big-integer>> ), do_encode_array( Dimensions, Has_nulls, Elem_ti, Encoded_elems ) end ); none -> {error, <<"Missing elem type info"/utf8>>} end end ). -file("src/pg_value.gleam", 359). ?DOC(" Encodes a Value as a PostgreSQL data type\n"). -spec encode(value(), pg_value@type_info:type_info()) -> {ok, bitstring()} | {error, binary()}. encode(Value, Info) -> case Value of null -> encode_null(); {bool, Val} -> encode_bool(Val, Info); {int, Val@1} -> encode_int(Val@1, Info); {float, Val@2} -> encode_float(Val@2, Info); {text, Val@3} -> encode_text(Val@3, Info); {bytea, Val@4} -> encode_bytea(Val@4, Info); {time, Val@5} -> encode_time(Val@5, Info); {date, Val@6} -> encode_date(Val@6, Info); {timestamp, Val@7} -> encode_timestamp(Val@7, Info); {timestamptz, Ts, Offset} -> encode_timestamptz(Ts, Offset, Info); {interval, Val@8} -> encode_interval(Val@8, Info); {array, Val@9} -> encode_array(Val@9, Info); {uuid, Val@10} -> encode_uuid(Val@10, Info); {hstore, Val@11} -> encode_hstore(Val@11, Info); {enum, Val@12} -> encode_enum(Val@12, Info); {json, Val@13} -> encode_json(Val@13, Info) end. -file("src/pg_value.gleam", 235). -spec array_to_string(list(value())) -> binary(). array_to_string(Array) -> Elems = case Array of [] -> <<""/utf8>>; [Val] -> to_string(Val); Vals -> _pipe = Vals, _pipe@1 = gleam@list:map(_pipe, fun to_string/1), gleam@string:join(_pipe@1, <<", "/utf8>>) end, <<<<"ARRAY["/utf8, Elems/binary>>/binary, "]"/utf8>>. -file("src/pg_value.gleam", 155). ?DOC(" Converts a `Value` to a string formatted properly for PostgreSQL\n"). -spec to_string(value()) -> binary(). to_string(Value) -> case Value of null -> <<"NULL"/utf8>>; {bool, Val} -> bool_to_string(Val); {int, Val@1} -> erlang:integer_to_binary(Val@1); {float, Val@2} -> gleam_stdlib:float_to_string(Val@2); {text, Val@3} -> text_to_string(Val@3); {bytea, Val@4} -> bytea_to_string(Val@4); {time, Val@5} -> time_to_string(Val@5); {date, Val@6} -> date_to_string(Val@6); {timestamp, Val@7} -> timestamp_to_string(Val@7); {timestamptz, Ts, Offset} -> timestamptz_to_string(Ts, Offset); {interval, Val@8} -> _pipe = pg_value@interval:to_iso8601_string(Val@8), single_quote(_pipe); {array, Vals} -> array_to_string(Vals); {uuid, Val@9} -> uuid_to_string(Val@9); {hstore, Val@10} -> hstore_to_string(Val@10); {enum, Val@11} -> _pipe@1 = gleam@string:replace(Val@11, <<"'"/utf8>>, <<"''"/utf8>>), single_quote(_pipe@1); {json, Val@12} -> _pipe@2 = gleam@json:to_string(Val@12), _pipe@3 = gleam@string:replace(_pipe@2, <<"'"/utf8>>, <<"''"/utf8>>), single_quote(_pipe@3) end.