Packages
amqp10_common
4.0.3
4.2.1
4.2.0
retired
4.1.6
4.0.3
4.0.3-rc.1
4.0.2
4.0.2-rc.2
4.0.2-rc.1
4.0.1
4.0.0
4.0.0-rc.2
4.0.0-rc.1
3.13.7
3.13.6
3.13.5
3.13.4
3.13.3
3.13.2
3.13.2-rc.1
3.13.1
3.13.0
3.13.0-rc.6
3.13.0-rc.5
3.13.0-rc.4
3.13.0-rc.3
3.13.0-rc.2
3.13.0-rc.1
3.12.14
3.12.13
3.12.12
3.12.11
3.12.10
3.12.9
3.12.8
3.12.7
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.12.0-rc.4
3.12.0-rc.3
3.12.0-rc.2
3.12.0-rc.1
3.11.28
3.11.27
3.11.26
3.11.25
3.11.24
3.11.23
3.11.22
3.11.21
3.11.20
3.11.19
3.11.18
3.11.17
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.11.0-rc.2
3.11.0-rc.1
3.11.0-1
3.10.25
3.10.24
3.10.23
3.10.22
3.10.21
3.10.20
3.10.19
3.10.18
3.10.17
3.10.16
3.10.15
3.10.14
3.10.13
3.10.12
3.10.11
3.10.10
3.10.9
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
retired
3.10.2-1
3.10.1
retired
3.10.0
retired
3.10.0-rc.6
3.10.0-rc.5
3.10.0-rc.1
3.9.29
3.9.28
3.9.27
3.9.26
3.9.25
3.9.24
3.9.23
3.9.22
3.9.21
3.9.20
3.9.19
3.9.18
retired
3.9.17
3.9.16
3.9.15
3.8.35
3.8.34
3.8.33
3.8.32
3.8.31
3.8.30
0.0.0-rc.1
Modules shared by rabbitmq-amqp1.0 and rabbitmq-amqp1.0-client
Current section
Files
Jump to
Current section
Files
src/serial_number.erl
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
%% https://www.ietf.org/rfc/rfc1982.txt
-module(serial_number).
-include("amqp10_types.hrl").
-export([add/2,
compare/2,
ranges/1,
in_range/3,
diff/2,
foldl/4]).
-ifdef(TEST).
-export([usort/1]).
-endif.
-type serial_number() :: sequence_no().
-export_type([serial_number/0]).
%% SERIAL_BITS = 32
%% 2 ^ SERIAL_BITS
-define(SERIAL_SPACE, 16#100000000).
%% 2 ^ (SERIAL_BITS - 1) - 1
-define(SERIAL_MAX_ADDEND, 16#7fffffff).
-spec add(serial_number(), non_neg_integer()) ->
serial_number().
add(S, N)
when N >= 0 andalso
N =< ?SERIAL_MAX_ADDEND ->
(S + N) rem ?SERIAL_SPACE;
add(S, N) ->
exit({undefined_serial_addition, S, N}).
%% 2 ^ (SERIAL_BITS - 1)
-define(COMPARE, 2_147_483_648).
-spec compare(serial_number(), serial_number()) ->
equal | less | greater.
compare(A, B) ->
if A =:= B ->
equal;
(A < B andalso B - A < ?COMPARE) orelse
(A > B andalso A - B > ?COMPARE) ->
less;
(A < B andalso B - A > ?COMPARE) orelse
(A > B andalso A - B < ?COMPARE) ->
greater;
true ->
exit({undefined_serial_comparison, A, B})
end.
-spec usort([serial_number()]) ->
[serial_number()].
usort(L) ->
lists:usort(fun(A, B) ->
compare(A, B) =/= greater
end, L).
%% Takes a list of serial numbers and returns tuples
%% {First, Last} representing contiguous serial numbers.
-spec ranges([serial_number()]) ->
[{First :: serial_number(), Last :: serial_number()}].
ranges([]) ->
[];
ranges(SerialNumbers) ->
[First | Rest] = usort(SerialNumbers),
ranges0(Rest, [{First, First}]).
ranges0([], Acc) ->
lists:reverse(Acc);
ranges0([H | Rest], [{First, Last} | AccRest] = Acc0) ->
case add(Last, 1) of
H ->
Acc = [{First, H} | AccRest],
ranges0(Rest, Acc);
_ ->
Acc = [{H, H} | Acc0],
ranges0(Rest, Acc)
end.
-spec in_range(serial_number(), serial_number(), serial_number()) ->
boolean().
in_range(S, First, Last) ->
case compare(S, First) of
less ->
false;
_ ->
case compare(S, Last) of
greater ->
false;
_ ->
true
end
end.
-define(SERIAL_DIFF_BOUND, 16#80000000).
-spec diff(serial_number(), serial_number()) -> integer().
diff(A, B) ->
Diff = A - B,
if Diff > (?SERIAL_DIFF_BOUND) ->
%% B is actually greater than A
- (?SERIAL_SPACE - Diff);
Diff < - (?SERIAL_DIFF_BOUND) ->
?SERIAL_SPACE + Diff;
Diff < ?SERIAL_DIFF_BOUND andalso Diff > -?SERIAL_DIFF_BOUND ->
Diff;
true ->
exit({undefined_serial_diff, A, B})
end.
-spec foldl(Fun, Acc0, First, Last) -> Acc1 when
Fun :: fun((serial_number(), AccIn) -> AccOut),
Acc0 :: term(),
Acc1 :: term(),
AccIn :: term(),
AccOut :: term(),
First :: serial_number(),
Last :: serial_number().
foldl(Fun, Acc0, Current, Last) ->
Acc = Fun(Current, Acc0),
case compare(Current, Last) of
less -> foldl(Fun, Acc, add(Current, 1), Last);
equal -> Acc
end.