blob: affd714336ec26cba808c2a197346ad8c3883020 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
6#define QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
7
8#include <limits>
9#include <ostream>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
QUICHE team5be974e2020-12-29 18:35:24 -050012#include "quic/platform/api/quic_export.h"
13#include "quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014
15namespace quic {
16
17// QuicPacketNumber can either initialized or uninitialized. An initialized
18// packet number is simply an ordinal number. A sentinel value is used to
19// represent an uninitialized packet number.
20class QUIC_EXPORT_PRIVATE QuicPacketNumber {
21 public:
22 // Construct an uninitialized packet number.
dschinazi3f6ccf42019-10-25 16:58:37 -070023 constexpr QuicPacketNumber() : packet_number_(UninitializedPacketNumber()) {}
24
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 // Construct a packet number from uint64_t. |packet_number| cannot equal the
26 // sentinel value.
dschinazi3f6ccf42019-10-25 16:58:37 -070027 explicit constexpr QuicPacketNumber(uint64_t packet_number)
28 : packet_number_(packet_number) {
vasilvv5cef78e2021-01-30 11:11:14 -080029 QUICHE_DCHECK_NE(UninitializedPacketNumber(), packet_number)
dschinazi3f6ccf42019-10-25 16:58:37 -070030 << "Use default constructor for uninitialized packet number";
31 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050032
wubfa63b6e2019-11-05 09:01:39 -080033 // The sentinel value representing an uninitialized packet number.
34 static constexpr uint64_t UninitializedPacketNumber() {
35 return std::numeric_limits<uint64_t>::max();
36 }
37
QUICHE teama6ef0a62019-03-07 20:34:33 -050038 // Packet number becomes uninitialized after calling this function.
39 void Clear();
40
QUICHE teamc264e362019-03-19 14:21:06 -070041 // Updates this packet number to be |new_value| if it is greater than current
42 // value.
43 void UpdateMax(QuicPacketNumber new_value);
44
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 // REQUIRES: IsInitialized() == true.
46 uint64_t Hash() const;
47
48 // Converts packet number to uint64_t.
49 // REQUIRES: IsInitialized() == true.
50 uint64_t ToUint64() const;
51
52 // Returns true if packet number is considered initialized.
53 bool IsInitialized() const;
54
55 // REQUIRES: IsInitialized() == true && ToUint64() <
56 // numeric_limits<uint64_t>::max() - 1.
57 QuicPacketNumber& operator++();
58 QuicPacketNumber operator++(int);
59 // REQUIRES: IsInitialized() == true && ToUint64() >= 1.
60 QuicPacketNumber& operator--();
61 QuicPacketNumber operator--(int);
62
63 // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() -
64 // ToUint64() > |delta|.
65 QuicPacketNumber& operator+=(uint64_t delta);
66 // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|.
67 QuicPacketNumber& operator-=(uint64_t delta);
68
dschinazi101d2eb2020-07-06 19:42:34 -070069 // Human-readable representation suitable for logging.
70 std::string ToString() const;
71
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
73 std::ostream& os,
74 const QuicPacketNumber& p);
75
76 private:
77 // All following operators REQUIRE operands.Initialized() == true.
78 friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs);
79 friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs);
80 friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs);
81 friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs);
82 friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs);
83 friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs);
84
85 // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|.
86 friend inline QuicPacketNumber operator+(QuicPacketNumber lhs,
87 uint64_t delta);
88 // REQUIRES: lhs.ToUint64() >= |delta|.
89 friend inline QuicPacketNumber operator-(QuicPacketNumber lhs,
90 uint64_t delta);
91 // REQUIRES: lhs >= rhs.
92 friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs);
93
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 uint64_t packet_number_;
95};
96
dschinazif25169a2019-10-23 08:12:18 -070097class QUIC_EXPORT_PRIVATE QuicPacketNumberHash {
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 public:
99 uint64_t operator()(QuicPacketNumber packet_number) const noexcept {
100 return packet_number.Hash();
101 }
102};
103
104inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800105 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
106 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107 return lhs.packet_number_ == rhs.packet_number_;
108}
109
110inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800111 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
112 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500113 return lhs.packet_number_ != rhs.packet_number_;
114}
115
116inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800117 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
118 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 return lhs.packet_number_ < rhs.packet_number_;
120}
121
122inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800123 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
124 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125 return lhs.packet_number_ <= rhs.packet_number_;
126}
127
128inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800129 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
130 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 return lhs.packet_number_ > rhs.packet_number_;
132}
133
134inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800135 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
136 << lhs << " vs. " << rhs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 return lhs.packet_number_ >= rhs.packet_number_;
138}
139
140inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) {
141#ifndef NDEBUG
vasilvv5cef78e2021-01-30 11:11:14 -0800142 QUICHE_DCHECK(lhs.IsInitialized());
143 QUICHE_DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(),
144 delta);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145#endif
146 return QuicPacketNumber(lhs.packet_number_ + delta);
147}
148
149inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) {
150#ifndef NDEBUG
vasilvv5cef78e2021-01-30 11:11:14 -0800151 QUICHE_DCHECK(lhs.IsInitialized());
152 QUICHE_DCHECK_GE(lhs.ToUint64(), delta);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153#endif
154 return QuicPacketNumber(lhs.packet_number_ - delta);
155}
156
157inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) {
vasilvv5cef78e2021-01-30 11:11:14 -0800158 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159 << lhs << " vs. " << rhs;
160 return lhs.packet_number_ - rhs.packet_number_;
161}
162
163} // namespace quic
164
165#endif // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_