Skip to main content

ratatui_kit/element/
key.rs

1use any_key::AnyHash;
2use std::sync::Arc;
3
4// 元素在协调(reconciliation)中的身份标识。
5//
6// 分两种形态以避免无谓的堆分配:
7// - [`ElementKey::Decl`]:仅由声明点稳定(宏在每个 `element!` 调用点烘焙一个 u128)。
8//   这是最常见情形(用户没写 `key:`),**零堆分配**。
9// - [`ElementKey::User`]:用户显式给了 `key:`(列表项需要),存 `(decl_key, 用户值)` 元组,
10//   经 `any_key::AnyHash` 类型擦除。**单次堆分配**(此前为 `Arc<Box<dyn>>` 的双重分配)。
11//
12// 两个变体天然不互相碰撞;`Decl(同一 u128)` 与此前「无用户 key 用同一 decl_key」语义一致。
13#[derive(Clone, PartialEq, Eq, Hash, Debug)]
14pub enum ElementKey {
15    // 仅声明点稳定的 key,零堆分配。
16    Decl(u128),
17    // 带用户值的稳定身份(`(decl_key, 用户值)`),单次堆分配。
18    User(Arc<dyn AnyHash + Send + Sync>),
19}
20
21impl ElementKey {
22    // 构造仅声明点稳定的 key(无用户 `key:`),零堆分配。
23    pub fn decl(decl_key: u128) -> Self {
24        Self::Decl(decl_key)
25    }
26
27    // 构造带用户值的 key。`key` 通常是 `(decl_key, 用户表达式)` 元组,
28    // 要求其类型 `Eq + Hash + 'static + Send + Sync`(经 `AnyHash` 擦除)。
29    pub fn user<T>(key: T) -> Self
30    where
31        T: Send + Sync + AnyHash,
32    {
33        Self::User(Arc::new(key))
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::ElementKey;
40    use std::collections::HashSet;
41
42    #[test]
43    fn decl_and_user_never_collide() {
44        // 不同变体永不相等,即便内含的 decl_key 相同。
45        assert_ne!(ElementKey::decl(42), ElementKey::user((42u128, "x")));
46    }
47
48    #[test]
49    fn decl_equality_by_value() {
50        assert_eq!(ElementKey::decl(7), ElementKey::decl(7));
51        assert_ne!(ElementKey::decl(7), ElementKey::decl(8));
52    }
53
54    #[test]
55    fn user_equality_by_tuple() {
56        assert_eq!(
57            ElementKey::user((1u128, "a")),
58            ElementKey::user((1u128, "a"))
59        );
60        // 同声明点(decl_key 相同)、不同用户值 → 不等(列表项区分的来源)。
61        assert_ne!(
62            ElementKey::user((1u128, "a")),
63            ElementKey::user((1u128, "b"))
64        );
65        // 不同声明点、相同用户值 → 不等(位置稳定性的来源)。
66        assert_ne!(
67            ElementKey::user((1u128, "a")),
68            ElementKey::user((2u128, "a"))
69        );
70    }
71
72    #[test]
73    fn hash_consistent_with_eq() {
74        let mut set = HashSet::new();
75        set.insert(ElementKey::decl(1));
76        set.insert(ElementKey::decl(1)); // 重复,去重
77        set.insert(ElementKey::user((1u128, "a")));
78        // decl(1) 去重为 1 个,user(..) 独立 1 个。
79        assert_eq!(set.len(), 2);
80    }
81}