13个版本 (破坏性)
0.10.0 | 2024年7月16日 |
---|---|
0.8.0 | 2023年10月20日 |
0.5.0 | 2023年7月28日 |
0.1.1 | 2023年1月6日 |
#643 in 网络编程
每月25次下载
23KB
202 行
此crate提供带环绕功能的两个字节的序列号。
序列号是分配给项目的递增标识符。在许多情况下,您可以使用u32
或u64
并结束,无需担心溢出。此类型的独特优势是它只使用与u16
相同的空间,通过环绕解决了溢出问题。
使用场景之一是在使用序列号签名网络数据包时,能够使用包含比使用u32
或u64
更多序列号的确认数据包进行响应。特别是对于UDP这样的协议,你可以在ack包中放入更多的数字,这会得到更多的冗余,也就更有可能确认所有接收到的数据包。
由于数字空间有限,最近分配的序列号可能与非常旧的序列号重复,但不会与其他最近分配的序列号重复。为了避免与这些非唯一数字产生歧义,RFC 1982 "序列号算术"为涉及此类序列号的计算定义了特殊的规则。
[dependencies]
serial-num = "0.10"
# or with additional features:
[dependencies]
serial-num = { version = "0.10", features = ["serde"] }
功能标志
以下功能标志实现了对Serial
类型的额外特性
arbitrary
:派生arbitrary
的Arbitrary
(⚠️需要std
)bincode
:派生bincode
的Decode/Encode
bitcode
:派生bitcode
的Decode/Encode
(⚠️需要std
)borsh
:派生borsh
的BorshDeserialize/BorshSerialize
bytemuck
:推导 bytemuck 的Pod/Zeroable
postcard
:推导 postcard 的Schema/MaxSize
rkyv
:推导 rkyv 的Archive/Deserialize/Serialize
rkyv-safe
:额外启用 rkyv 的安全 APIserde
:推导 serde 的Deserialize/Serialize
speedy
:推导 speedy 的Readable/Writable
(⚠️ 需要std
)
用法
简单示例
use serial_num::Serial;
// the default is a reference point - not serial number "zero"
let mut a = Serial::default();
let mut b = Serial::default();
let mut c = Serial::default();
// three ways to increase
let x = a.increase_get(); // increase, then copy
let y = b.get_increase(); // copy, then increase
c.increase();
assert!(y.precedes(x));
assert_eq!(-1_i16, y.diff(x)); // "diff()" is signed
assert_eq!(1_u16, y.dist(x)); // "dist()" is unsigned
// addition is the same as calling "increase()" n times
assert_eq!(y + 1_u16, x);
环绕示例
use serial_num::Serial;
// a serial number can be increased indefinitely
let mut x = Serial::default();
for _ in 0..u16::MAX {
x.increase();
}
let x = x + u16::MAX + u16::MAX + u16::MAX;
// comparison is trivial as long as two serial numbers have
// a distance of less than half of our number space (32767).
let a = Serial::default() + 5;
let b = Serial::default() + 32000;
assert!(a.precedes(b)); // 5th successor < 32000th successor
// but: the comparison flips if the distance is larger
let a = Serial::default() + 5;
let b = Serial::default() + 65000;
assert!(a.succeeds(b)); // 5th successor > 65000th successor
// this means that you get the right ordering as long as
// you compare one serial number at most with one that
// is its 32767th successor:
let num = Serial::default();
assert!(num.precedes(num + 32767)); // 0 < 32767 (still intuitive)
assert!(num.succeeds(num + 32768)); // 0 > 32768 (flip #1)
assert!(num.succeeds(num + 65534)); // 0 > 65534
assert!(num == num + 65535); // 0 == 65535 (due to same internal representation)
assert!(num.precedes(num + 65535 + 1)); // 0 < 65536 (flip #2)
NAN
值
use serial_num::Serial;
// "NAN" exists to have value representing "no serial number",
// since it saves encoding space vs wrapping Serial in an Option.
let nan = Serial::NAN;
let num = Serial::default();
// you can check whether a serial number is NAN
assert!(nan.is_nan());
// NAN cannot be increased
assert_eq!(Serial::NAN, nan + 1_u16);
// distance between two NAN values is zero
assert_eq!(0_u16, nan.dist(nan));
assert_eq!(0_i16, nan.diff(nan));
// distance and difference of non-NAN to NAN is the maximum distance
assert_eq!(32_767_u16, num.dist(nan));
assert_eq!(32_767_u16, nan.dist(num));
assert_eq!(32_767_i16, num.diff(nan));
assert_eq!(32_767_i16, nan.diff(num));
// partial ordering does not include the NAN value
assert_eq!(None, nan.partial_cmp(num));
assert!(!nan.precedes(num) && !nan.succeeds(num));
依赖
~0–1MB
~20K SLoC