-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", 167). -spec list_reverse_loop(list(ICQ), list(ICQ)) -> list(ICQ). list_reverse_loop(L, Acc) -> case L of [] -> Acc; [X | Rest] -> list_reverse_loop(Rest, [X | Acc]) end. -file("src/postgleam/codec/numeric.gleam", 163). -spec list_reverse(list(ICN)) -> list(ICN). list_reverse(L) -> list_reverse_loop(L, []). -file("src/postgleam/codec/numeric.gleam", 60). -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", 152). -spec split_at_loop(list(ICI), integer(), list(ICI)) -> {list(ICI), list(ICI)}. 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", 148). -spec split_at(list(ICE), integer()) -> {list(ICE), list(ICE)}. split_at(L, N) -> split_at_loop(L, N, []). -file("src/postgleam/codec/numeric.gleam", 175). ?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", 27). -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", 183). -spec repeat_char(binary(), integer()) -> binary(). repeat_char(C, N) -> case N =< 0 of true -> <<""/utf8>>; false -> <> end. -file("src/postgleam/codec/numeric.gleam", 137). -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", 107). -spec int_digits_to_string(list(integer()), boolean()) -> binary(). int_digits_to_string(Digits, Is_first) -> case Digits of [] -> <<""/utf8>>; [D | Rest] -> S = case Is_first of true -> erlang:integer_to_binary(D); false -> pad_digit(D) end, <> end. -file("src/postgleam/codec/numeric.gleam", 130). -spec frac_raw(list(integer())) -> binary(). frac_raw(Digits) -> case Digits of [] -> <<""/utf8>>; [D | Rest] -> <<(pad_digit(D))/binary, (frac_raw(Rest))/binary>> end. -file("src/postgleam/codec/numeric.gleam", 120). -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", 71). -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", 48). -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", 37). -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", 23). -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", 13). -spec matcher() -> postgleam@codec:codec_matcher(). matcher() -> {codec_matcher, <<"numeric"/utf8>>, [1700], none, binary, fun build/1}.