1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};

/// `==` 和 `!=` 等价于比较它们的底层字节的类型。
///
/// 重要的是,这意味着没有浮点类型,因为它们具有不同的字节表示 (如 `-0` 和 `+0`),它们比较相同。
/// 由于字节数组是 `Eq`,这意味着这些类型可能也是 `Eq`,但这在技术上并不是使用此 trait 所必需的。
///
/// `Rhs`*事实上*总是 `Self`,但单独的参数对于避免在使用它时出现 `specializing impl repeats parameter` 错误很重要。
///
///
/// # Safety
///
/// - `Self` 和 `Rhs` 没有填充。
/// - `Self` 和 `Rhs` 具有相同的布局 (大小和对齐方式)。
/// - `Self` 和 `Rhs` 都没有出处,因此整数比较是正确的。
/// - `<Self as PartialEq<Rhs>>::{eq,ne}` 相当于比较字节。
///
///
#[rustc_specialization_trait]
pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {}

macro_rules! is_bytewise_comparable {
    ($($t:ty),+ $(,)?) => {$(
        unsafe impl BytewiseEq for $t {}
    )+};
}

// SAFETY: 所有普通整数类型都没有填充,也不是指针。
is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

// SAFETY: 这些有*niches*,但没有*padding*也没有*provenance*,所以我们可以直接比较它们。
//
is_bytewise_comparable!(bool, char, super::Ordering);

// SAFETY: 类似地,非零类型有一个 niche,但没有 undef 和指针,它们比较像它们的底层数字类型。
//
is_bytewise_comparable!(
    NonZeroU8,
    NonZeroU16,
    NonZeroU32,
    NonZeroU64,
    NonZeroU128,
    NonZeroUsize,
    NonZeroI8,
    NonZeroI16,
    NonZeroI32,
    NonZeroI64,
    NonZeroI128,
    NonZeroIsize,
);

// SAFETY: NonZero 类型保证了 "null" 优化,因此在 `Option` 中按位进行相等比较也是安全的。
// 为 `Option` 定义 `PartialOrd` 的方式意味着这对有符号类型的 `<` 或 `>` 不起作用,但因为我们只做 `==`,所以很好。
//
//
is_bytewise_comparable!(
    Option<NonZeroU8>,
    Option<NonZeroU16>,
    Option<NonZeroU32>,
    Option<NonZeroU64>,
    Option<NonZeroU128>,
    Option<NonZeroUsize>,
    Option<NonZeroI8>,
    Option<NonZeroI16>,
    Option<NonZeroI32>,
    Option<NonZeroI64>,
    Option<NonZeroI128>,
    Option<NonZeroIsize>,
);

macro_rules! is_bytewise_comparable_array_length {
    ($($n:literal),+ $(,)?) => {$(
        // SAFETY: 数组在元素之间没有填充,所以如果元素是 `BytewiseEq`,那么整个数组也可以。
        //
        unsafe impl<T: BytewiseEq<U>, U> BytewiseEq<[U; $n]> for [T; $n] {}
    )+};
}

// 令人沮丧的是,这不能成为 const - 泛型,因为它会出错: 特化 impl 重复参数 `N` 所以只对几个貌似常见的参数做。
//
//
is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64);