Current section
Files
Jump to
Current section
Files
src/postgleam@codec@numeric.erl
-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(IIC), list(IIC)) -> list(IIC).
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(IHZ)) -> list(IHZ).
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
<<D:16, Rest/bitstring>> ->
read_digits(Rest, Count - 1, [D | Acc]);
_ ->
list_reverse(Acc)
end
end.
-file("src/postgleam/codec/numeric.gleam", 176).
-spec split_at_loop(list(IHU), integer(), list(IHU)) -> {list(IHU), list(IHU)}.
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(IHQ), integer()) -> {list(IHQ), list(IHQ)}.
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, <<Acc/bitstring, S@1/binary>>)
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, <<Acc/bitstring, S@1/binary>>)
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 ->
<<Raw/binary, (repeat_char(<<"0"/utf8>>, 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 ->
<<<<Prefix/binary, "0."/utf8>>/binary,
(repeat_char(<<"0"/utf8>>, Scale))/binary>>;
false ->
<<Prefix/binary, "0"/utf8>>
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),
<<<<<<Prefix/binary, Int_str@1/binary>>/binary, "."/utf8>>/binary,
Frac_str/binary>>;
false ->
<<Prefix/binary, Int_str@1/binary>>
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};
<<Ndigits:16, Weight:16/signed, Sign:16, Scale:16, Rest/bitstring>> ->
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}.