-module(postgleam@codec@numeric). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/postgleam/codec/numeric.gleam"). -export([encode/1, decode/1, matcher/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. -file("src/postgleam/codec/numeric.gleam", 191). -spec list_reverse_loop(list(IRQ), list(IRQ)) -> list(IRQ). list_reverse_loop(L, Acc) -> case L of [] -> Acc; [X | Rest] -> list_reverse_loop(Rest, [X | Acc]) end. -file("src/postgleam/codec/numeric.gleam", 187). -spec list_reverse(list(IRN)) -> list(IRN). list_reverse(L) -> list_reverse_loop(L, []). -file("src/postgleam/codec/numeric.gleam", 61). -spec read_digits(bitstring(), integer(), list(integer())) -> list(integer()). read_digits(Data, Count, Acc) -> case Count of 0 -> list_reverse(Acc); _ -> case Data of <> -> read_digits(Rest, Count - 1, [D | Acc]); _ -> list_reverse(Acc) end end. -file("src/postgleam/codec/numeric.gleam", 176). -spec split_at_loop(list(IRI), integer(), list(IRI)) -> {list(IRI), list(IRI)}. split_at_loop(L, N, Acc) -> case N =< 0 of true -> {list_reverse(Acc), L}; false -> case L of [] -> {list_reverse(Acc), []}; [X | Rest] -> split_at_loop(Rest, N - 1, [X | Acc]) end end. -file("src/postgleam/codec/numeric.gleam", 172). -spec split_at(list(IRE), integer()) -> {list(IRE), list(IRE)}. split_at(L, N) -> split_at_loop(L, N, []). -file("src/postgleam/codec/numeric.gleam", 199). ?DOC(" Encode a numeric string to PostgreSQL binary format\n"). -spec encode_numeric_string(binary()) -> {ok, bitstring()} | {error, binary()}. encode_numeric_string(S) -> {ok, postgleam_ffi:encode_numeric(S)}. -file("src/postgleam/codec/numeric.gleam", 28). -spec encode(postgleam@value:value()) -> {ok, bitstring()} | {error, binary()}. encode(Val) -> case Val of na_n -> {ok, <<0:16, 0:16, 16#C000:16, 0:16>>}; pos_infinity -> {ok, <<0:16, 0:16, 16#D000:16, 0:16>>}; neg_infinity -> {ok, <<0:16, 0:16, 16#F000:16, 0:16>>}; {numeric, S} -> encode_numeric_string(S); _ -> {error, <<"numeric codec: expected Numeric, NaN, PosInfinity, or NegInfinity"/utf8>>} end. -file("src/postgleam/codec/numeric.gleam", 161). -spec pad_digit(integer()) -> binary(). pad_digit(D) -> S = erlang:integer_to_binary(D), Len = string:length(S), case Len of 1 -> <<"000"/utf8, S/binary>>; 2 -> <<"00"/utf8, S/binary>>; 3 -> <<"0"/utf8, S/binary>>; _ -> S end. -file("src/postgleam/codec/numeric.gleam", 112). -spec int_digits_to_bytes(list(integer()), boolean(), bitstring()) -> binary(). int_digits_to_bytes(Digits, Is_first, Acc) -> case Digits of [] -> case gleam@bit_array:to_string(Acc) of {ok, S} -> S; {error, _} -> <<""/utf8>> end; [D | Rest] -> S@1 = case Is_first of true -> erlang:integer_to_binary(D); false -> pad_digit(D) end, int_digits_to_bytes(Rest, false, <>) end. -file("src/postgleam/codec/numeric.gleam", 108). -spec int_digits_to_string(list(integer()), boolean()) -> binary(). int_digits_to_string(Digits, Is_first) -> int_digits_to_bytes(Digits, Is_first, <<>>). -file("src/postgleam/codec/numeric.gleam", 147). -spec frac_raw_bytes(list(integer()), bitstring()) -> binary(). frac_raw_bytes(Digits, Acc) -> case Digits of [] -> case gleam@bit_array:to_string(Acc) of {ok, S} -> S; {error, _} -> <<""/utf8>> end; [D | Rest] -> S@1 = pad_digit(D), frac_raw_bytes(Rest, <>) end. -file("src/postgleam/codec/numeric.gleam", 143). -spec frac_raw(list(integer())) -> binary(). frac_raw(Digits) -> frac_raw_bytes(Digits, <<>>). -file("src/postgleam/codec/numeric.gleam", 207). -spec repeat_char(binary(), integer()) -> binary(). repeat_char(C, N) -> case N =< 0 of true -> <<""/utf8>>; false -> string:copies(C, N) end. -file("src/postgleam/codec/numeric.gleam", 133). -spec frac_digits_to_string(list(integer()), integer()) -> binary(). frac_digits_to_string(Digits, Scale) -> Raw = frac_raw(Digits), Len = string:length(Raw), case Len >= Scale of true -> binary:part(Raw, 0, Scale); false -> <>, Scale - Len))/binary>> end. -file("src/postgleam/codec/numeric.gleam", 72). -spec digits_to_string(list(integer()), integer(), integer(), integer()) -> binary(). digits_to_string(Digits, Weight, Scale, Sign) -> Prefix = case Sign of 16#4000 -> <<"-"/utf8>>; _ -> <<""/utf8>> end, case Digits of [] -> case Scale > 0 of true -> <<<>/binary, (repeat_char(<<"0"/utf8>>, Scale))/binary>>; false -> <> end; _ -> Int_groups = Weight + 1, {Int_digits, Frac_digits} = split_at(Digits, Int_groups), Int_str = int_digits_to_string(Int_digits, true), Int_str@1 = case Int_str of <<""/utf8>> -> <<"0"/utf8>>; S -> S end, case Scale > 0 of true -> Frac_str = frac_digits_to_string(Frac_digits, Scale), <<<<<>/binary, "."/utf8>>/binary, Frac_str/binary>>; false -> <> end end. -file("src/postgleam/codec/numeric.gleam", 49). -spec decode_numeric(integer(), integer(), integer(), integer(), bitstring()) -> {ok, postgleam@value:value()} | {error, binary()}. decode_numeric(Ndigits, Weight, Sign, Scale, Data) -> Digits = read_digits(Data, Ndigits, []), Str = digits_to_string(Digits, Weight, Scale, Sign), {ok, {numeric, Str}}. -file("src/postgleam/codec/numeric.gleam", 38). -spec decode(bitstring()) -> {ok, postgleam@value:value()} | {error, binary()}. decode(Data) -> case Data of <<_:16, _:16/signed, 16#C000:16, _:16>> -> {ok, na_n}; <<_:16, _:16/signed, 16#D000:16, _:16>> -> {ok, pos_infinity}; <<_:16, _:16/signed, 16#F000:16, _:16>> -> {ok, neg_infinity}; <> -> decode_numeric(Ndigits, Weight, Sign, Scale, Rest); _ -> {error, <<"numeric codec: invalid data"/utf8>>} end. -file("src/postgleam/codec/numeric.gleam", 24). -spec build(integer()) -> postgleam@codec:codec(). build(Type_oid) -> {codec, <<"numeric"/utf8>>, Type_oid, binary, fun encode/1, fun decode/1}. -file("src/postgleam/codec/numeric.gleam", 14). -spec matcher() -> postgleam@codec:codec_matcher(). matcher() -> {codec_matcher, <<"numeric"/utf8>>, [1700], none, binary, fun build/1}.