diff options
Diffstat (limited to 'deps/rabbitmq_amqp1_0/src/rabbit_amqp1_0_util.erl')
-rw-r--r-- | deps/rabbitmq_amqp1_0/src/rabbit_amqp1_0_util.erl | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/deps/rabbitmq_amqp1_0/src/rabbit_amqp1_0_util.erl b/deps/rabbitmq_amqp1_0/src/rabbit_amqp1_0_util.erl new file mode 100644 index 0000000000..9d9ad5044d --- /dev/null +++ b/deps/rabbitmq_amqp1_0/src/rabbit_amqp1_0_util.erl @@ -0,0 +1,72 @@ +%% 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-2020 VMware, Inc. or its affiliates. All rights reserved. +%% + +-module(rabbit_amqp1_0_util). + +-include("rabbit_amqp1_0.hrl"). + +-export([protocol_error/3]). +-export([serial_add/2, serial_compare/2, serial_diff/2]). + +-export_type([serial_number/0]). +-type serial_number() :: non_neg_integer(). +-type serial_compare_result() :: 'equal' | 'less' | 'greater'. + +-spec serial_add(serial_number(), non_neg_integer()) -> + serial_number(). +-spec serial_compare(serial_number(), serial_number()) -> + serial_compare_result(). +-spec serial_diff(serial_number(), serial_number()) -> + integer(). + +protocol_error(Condition, Msg, Args) -> + exit(#'v1_0.error'{ + condition = Condition, + description = {utf8, list_to_binary( + lists:flatten(io_lib:format(Msg, Args)))} + }). + +%% Serial arithmetic for unsigned ints. +%% http://www.faqs.org/rfcs/rfc1982.html +%% SERIAL_BITS = 32 + +%% 2 ^ SERIAL_BITS +-define(SERIAL_MAX, 16#100000000). +%% 2 ^ (SERIAL_BITS - 1) - 1 +-define(SERIAL_MAX_ADDEND, 16#7fffffff). + +serial_add(S, N) when N =< ?SERIAL_MAX_ADDEND -> + (S + N) rem ?SERIAL_MAX; +serial_add(S, N) -> + exit({out_of_bound_serial_addition, S, N}). + +serial_compare(A, B) -> + if A =:= B -> + equal; + (A < B andalso B - A < ?SERIAL_MAX_ADDEND) orelse + (A > B andalso A - B > ?SERIAL_MAX_ADDEND) -> + less; + (A < B andalso B - A > ?SERIAL_MAX_ADDEND) orelse + (A > B andalso B - A < ?SERIAL_MAX_ADDEND) -> + greater; + true -> exit({indeterminate_serial_comparison, A, B}) + end. + +-define(SERIAL_DIFF_BOUND, 16#80000000). + +serial_diff(A, B) -> + Diff = A - B, + if Diff > (?SERIAL_DIFF_BOUND) -> + %% B is actually greater than A + - (?SERIAL_MAX - Diff); + Diff < - (?SERIAL_DIFF_BOUND) -> + ?SERIAL_MAX + Diff; + Diff < ?SERIAL_DIFF_BOUND andalso Diff > -?SERIAL_DIFF_BOUND -> + Diff; + true -> + exit({indeterminate_serial_diff, A, B}) + end. |