Current section

Files

Jump to
gleam_bson src bson@object_id.erl
Raw

src/bson@object_id.erl

-module(bson@object_id).
-compile(no_auto_import).
-export([new/0, get_timestamp/1, to_string/1, to_int_list/1, to_bit_string/1, from_string/1, from_int_list/1, from_bit_string/1]).
-export_type([object_id/0, time_unit/0]).
-opaque object_id() :: {object_id, bitstring()}.
-type time_unit() :: second.
-spec new() -> object_id().
new() ->
Moment = os:system_time(second),
Counter = gleam@int:random(0, 16#ffffff),
{ok, Hostname@1} = case inet:gethostname() of
{ok, Hostname} -> {ok, Hostname};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"bson/object_id"/utf8>>,
function => <<"new"/utf8>>,
line => 19})
end,
<<Machine_id:24, _@1/bitstring>> = gleam@crypto:hash(sha256, Hostname@1),
{ok, String_pid@1} = case begin
_pipe = os:getpid(),
_pipe@1 = gleam@list:fold(
_pipe,
<<>>,
fun(Acc, C) -> <<Acc/bitstring, C>> end
),
gleam@bit_string:to_string(_pipe@1)
end of
{ok, String_pid} -> {ok, String_pid};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"bson/object_id"/utf8>>,
function => <<"new"/utf8>>,
line => 23})
end,
{ok, Pid@1} = case gleam@int:parse(String_pid@1) of
{ok, Pid} -> {ok, Pid};
_try@2 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@2,
module => <<"bson/object_id"/utf8>>,
function => <<"new"/utf8>>,
line => 28})
end,
{ok, Id@1} = case begin
_pipe@2 = <<Moment:32/big,
Machine_id:24/big,
Pid@1:16/big,
Counter:24/big>>,
from_bit_string(_pipe@2)
end of
{ok, Id} -> {ok, Id};
_try@3 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@3,
module => <<"bson/object_id"/utf8>>,
function => <<"new"/utf8>>,
line => 30})
end,
Id@1.
-spec get_timestamp(object_id()) -> integer().
get_timestamp(Id) ->
case Id of
{object_id, <<Timestamp:32/big, _@1/bitstring>>} ->
Timestamp
end.
-spec to_string(object_id()) -> binary().
to_string(Id) ->
case Id of
{object_id, Value} ->
to_string_internal(Value, <<""/utf8>>)
end.
-spec to_int_list(object_id()) -> list(integer()).
to_int_list(Id) ->
case Id of
{object_id, Value} ->
to_int_list_internal(Value, [])
end.
-spec to_bit_string(object_id()) -> bitstring().
to_bit_string(Id) ->
case Id of
{object_id, Value} ->
Value
end.
-spec from_string(binary()) -> {ok, object_id()} | {error, nil}.
from_string(Id) ->
case gleam@string:length(Id) of
24 ->
case begin
_pipe = Id,
_pipe@1 = gleam@string:to_graphemes(_pipe),
gleam@list:try_map(_pipe@1, fun to_digit/1)
end of
{ok, Codes} ->
_pipe@2 = Codes,
_pipe@3 = gleam@list:sized_chunk(_pipe@2, 2),
_pipe@4 = gleam@list:map(
_pipe@3,
fun(Pair) ->
[High, Low] = Pair,
<<High:4, Low:4>>
end
),
_pipe@5 = gleam@bit_string:concat(_pipe@4),
_pipe@6 = {object_id, _pipe@5},
{ok, _pipe@6};
{error, nil} ->
{error, nil}
end;
_@1 ->
{error, nil}
end.
-spec from_int_list(list(integer())) -> {ok, object_id()} | {error, nil}.
from_int_list(Id) ->
case gleam@list:length(Id) of
12 ->
case gleam@list:try_fold(
Id,
<<>>,
fun(Acc, Code) -> case (Code >= 0) andalso (Code =< 255) of
true ->
_pipe = gleam@bit_string:append(Acc, <<Code>>),
{ok, _pipe};
false ->
{error, nil}
end end
) of
{ok, Id@1} ->
{ok, {object_id, Id@1}};
{error, nil} ->
{error, nil}
end;
24 ->
case gleam@list:try_map(
Id,
fun(Code@1) -> case (Code@1 >= 0) andalso (Code@1 =< 15) of
true ->
{ok, Code@1};
false ->
{error, nil}
end end
) of
{ok, Codes} ->
_pipe@1 = Codes,
_pipe@2 = gleam@list:sized_chunk(_pipe@1, 2),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Pair) ->
[High, Low] = Pair,
<<Num:8>> = <<High:4, Low:4>>,
Num
end
),
_pipe@5 = gleam@list:fold(
_pipe@3,
<<>>,
fun(Acc@1, Code@2) ->
_pipe@4 = Acc@1,
gleam@bit_string:append(_pipe@4, <<Code@2>>)
end
),
_pipe@6 = {object_id, _pipe@5},
{ok, _pipe@6};
{error, nil} ->
{error, nil}
end;
_@1 ->
{error, nil}
end.
-spec from_bit_string(bitstring()) -> {ok, object_id()} | {error, nil}.
from_bit_string(Id) ->
case gleam@bit_string:byte_size(Id) of
12 ->
{ok, {object_id, Id}};
_@1 ->
{error, nil}
end.
-spec to_string_internal(bitstring(), binary()) -> binary().
to_string_internal(Remaining, Storage) ->
<<High:4, Low:4, Remaining@1/binary>> = Remaining,
New_storage = begin
_pipe = Storage,
_pipe@1 = gleam@string:append(_pipe, to_char(High)),
gleam@string:append(_pipe@1, to_char(Low))
end,
case gleam@bit_string:byte_size(Remaining@1) of
0 ->
New_storage;
_@1 ->
to_string_internal(Remaining@1, New_storage)
end.
-spec to_int_list_internal(bitstring(), list(integer())) -> list(integer()).
to_int_list_internal(Remaining, Storage) ->
<<Num:8, Remaining@1/binary>> = Remaining,
New_storage = begin
_pipe = Storage,
_pipe@1 = gleam@list:reverse(_pipe),
_pipe@2 = gleam@list:prepend(_pipe@1, Num),
gleam@list:reverse(_pipe@2)
end,
case gleam@bit_string:byte_size(Remaining@1) of
0 ->
New_storage;
_@1 ->
to_int_list_internal(Remaining@1, New_storage)
end.
-spec to_digit(binary()) -> {ok, integer()} | {error, nil}.
to_digit(Char) ->
<<Code>> = gleam@bit_string:from_string(Char),
case Code of
Code@1 when (Code@1 >= 48) andalso (Code@1 =< 57) ->
<<_@1:4, Num:4>> = gleam@bit_string:from_string(Char),
{ok, Num};
Code@2 when ((Code@2 >= 65) andalso (Code@2 =< 70)) orelse ((Code@2 >= 97) andalso (Code@2 =< 102)) ->
<<_@2:5, Additive:3>> = gleam@bit_string:from_string(Char),
{ok, 9 + Additive};
_@3 ->
{error, nil}
end.
-spec to_char(integer()) -> binary().
to_char(Digit) ->
Ch = case Digit < 10 of
true ->
Digit + 48;
false ->
Digit + 87
end,
{ok, Digit@2} = case gleam@bit_string:to_string(<<Ch>>) of
{ok, Digit@1} -> {ok, Digit@1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"bson/object_id"/utf8>>,
function => <<"to_char"/utf8>>,
line => 201})
end,
Digit@2.