Skip to main content

zenith_foundation/
token.rs

1//! 所有权令牌模块
2//!
3//! 实现 FrameToken 所有权令牌,通过 `PhantomData<*const ()>` 在编译期保证
4//! 所有权唯一,防止资源被复制或伪造(!Copy + !Clone)。
5
6use std::fmt;
7use std::marker::PhantomData;
8
9use crate::error::{CoreError, CoreResult};
10use crate::frame::FrameId;
11
12/// 所有权令牌
13///
14/// 每个令牌唯一对应一个 Frame,通过类型系统在编译期保证:
15/// - 不可跨线程(!Send + !Sync,通过 `PhantomData<*const ()>` 实现:
16///   原始指针自动不实现 Send/Sync,令牌无法传递或共享到其他线程)
17/// - 不可复制/克隆(!Copy + !Clone,通过不 derive 相应 trait 实现)
18/// - 不可在外部构造(`pub(crate)` 构造函数)
19///
20/// # 所有权守恒
21///
22/// 令牌的生命周期必须严格遵循以下规则:
23/// 1. 令牌创建后只能有一个所有者
24/// 2. 所有权转移必须是原子操作
25/// 3. 令牌销毁前必须归还到 FramePool
26pub struct FrameToken {
27    /// Frame ID
28    frame_id: FrameId,
29    /// 域ID
30    domain_id: u32,
31    /// 代际号
32    generation: u64,
33    /// Epoch编号
34    epoch: u64,
35    /// PhantomData 用于禁用 Send 和 Sync:
36    /// 原始指针 *const () 自动不实现 Send/Sync,经 PhantomData 传递到整个结构体,
37    /// 使令牌被类型系统钉死在创建它的 Worker 线程上
38    _not_send_sync: PhantomData<*const ()>,
39}
40
41impl fmt::Debug for FrameToken {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        f.debug_struct("FrameToken")
44            .field("frame_id", &self.frame_id)
45            .field("domain_id", &self.domain_id)
46            .field("generation", &self.generation)
47            .field("epoch", &self.epoch)
48            .finish()
49    }
50}
51
52impl FrameToken {
53    /// 创建新的所有权令牌
54    ///
55    /// # Arguments
56    /// * `frame_id` - Frame ID
57    /// * `domain_id` - 域ID
58    /// * `generation` - 代际号
59    /// * `epoch` - Epoch编号
60    ///
61    /// # Returns
62    /// 新的 FrameToken 实例
63    ///
64    /// # Safety
65    /// 此方法仅限 crate 内部使用,外部禁止构造令牌
66    pub(crate) fn new(
67        frame_id: FrameId,
68        domain_id: u32,
69        generation: u64,
70        epoch: u64,
71    ) -> Self {
72        Self {
73            frame_id,
74            domain_id,
75            generation,
76            epoch,
77            _not_send_sync: PhantomData,
78        }
79    }
80
81    /// 获取 Frame ID
82    pub fn frame_id(&self) -> FrameId {
83        self.frame_id
84    }
85
86    /// 获取域ID
87    pub fn domain_id(&self) -> u32 {
88        self.domain_id
89    }
90
91    /// 获取代际号
92    pub fn generation(&self) -> u64 {
93        self.generation
94    }
95
96    /// 获取Epoch编号
97    pub fn epoch(&self) -> u64 {
98        self.epoch
99    }
100
101    /// 验证令牌是否属于指定域和代际
102    ///
103    /// 使用恒定时间比较防止时序侧信道攻击。
104    ///
105    /// # Arguments
106    /// * `expected_domain` - 期望的域ID
107    /// * `expected_generation` - 期望的代际号
108    ///
109    /// # Returns
110    /// * `Ok(())` - 验证通过
111    /// * `Err(CoreError::OwnershipViolation)` - 验证失败
112    pub fn verify_ownership(
113        &self,
114        expected_domain: u32,
115        expected_generation: u64,
116    ) -> CoreResult<()> {
117        let domain_ok = crate::constant_time_eq_u32(self.domain_id, expected_domain);
118        let gen_ok = crate::constant_time_eq_u64(self.generation, expected_generation);
119
120        if domain_ok && gen_ok {
121            Ok(())
122        } else {
123            Err(CoreError::ownership_violation(
124                if domain_ok { "valid domain" } else { "invalid domain" },
125                if gen_ok { "valid generation" } else { "invalid generation" },
126            ))
127        }
128    }
129
130    /// 验证令牌是否属于指定Epoch
131    ///
132    /// 使用恒定时间比较防止时序侧信道攻击。
133    ///
134    /// # Arguments
135    /// * `expected_epoch` - 期望的Epoch编号
136    ///
137    /// # Returns
138    /// * `Ok(())` - 验证通过
139    /// * `Err(CoreError::StateConflict)` - 验证失败
140    pub fn verify_epoch(&self, expected_epoch: u64) -> CoreResult<()> {
141        if crate::constant_time_eq_u64(self.epoch, expected_epoch) {
142            Ok(())
143        } else {
144            Err(CoreError::state_conflict(
145                format!("epoch={}", self.epoch),
146                format!("epoch={}", expected_epoch),
147            ))
148        }
149    }
150
151    /// 消费令牌并获取 Frame ID
152    ///
153    /// 此方法消费令牌,返回 Frame ID。
154    /// 令牌被消费后不可再使用(self 在函数结束时自动释放所有权)。
155    ///
156    /// # Returns
157    /// Frame ID
158    pub fn into_frame_id(self) -> FrameId {
159        self.frame_id
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_token_creation() {
169        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
170        assert_eq!(token.frame_id(), FrameId::new(1));
171        assert_eq!(token.domain_id(), 0);
172        assert_eq!(token.generation(), 1);
173        assert_eq!(token.epoch(), 0);
174    }
175
176    #[test]
177    fn test_verify_ownership_success() {
178        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
179        assert!(token.verify_ownership(0, 1).is_ok());
180    }
181
182    #[test]
183    fn test_verify_ownership_failure_domain() {
184        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
185        let result = token.verify_ownership(1, 1);
186        assert!(result.is_err());
187    }
188
189    #[test]
190    fn test_verify_ownership_failure_generation() {
191        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
192        let result = token.verify_ownership(0, 2);
193        assert!(result.is_err());
194    }
195
196    #[test]
197    fn test_verify_epoch_success() {
198        let token = FrameToken::new(FrameId::new(1), 0, 1, 42);
199        assert!(token.verify_epoch(42).is_ok());
200    }
201
202    #[test]
203    fn test_verify_epoch_failure() {
204        let token = FrameToken::new(FrameId::new(1), 0, 1, 42);
205        let result = token.verify_epoch(43);
206        assert!(result.is_err());
207    }
208
209    #[test]
210    fn test_into_frame_id() {
211        let token = FrameToken::new(FrameId::new(100), 0, 1, 0);
212        let id = token.into_frame_id();
213        assert_eq!(id, FrameId::new(100));
214    }
215
216    #[test]
217    fn test_token_is_not_copy() {
218        // 编译期检查:FrameToken 不可复制
219        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
220        let _token2 = token; // 所有权转移
221        // let _token3 = token; // 编译错误:value borrowed after move
222    }
223
224    // ===== verify_ownership 双条件同时失败 =====
225
226    #[test]
227    fn test_verify_ownership_both_fail() {
228        let token = FrameToken::new(FrameId::new(1), 0, 1, 0);
229        let result = token.verify_ownership(99, 99);
230        assert!(result.is_err());
231    }
232
233    // ===== verify_epoch 测试(gen=0 边界情况) =====
234
235    #[test]
236    fn test_verify_epoch_success_gen0() {
237        let token = FrameToken::new(FrameId::new(1), 0, 0, 42);
238        assert!(token.verify_epoch(42).is_ok());
239    }
240
241    #[test]
242    fn test_verify_epoch_failure_gen0() {
243        let token = FrameToken::new(FrameId::new(1), 0, 0, 42);
244        let result = token.verify_epoch(100);
245        assert!(result.is_err());
246    }
247
248    #[test]
249    fn test_verify_epoch_zero() {
250        let token = FrameToken::new(FrameId::new(1), 0, 0, 0);
251        assert!(token.verify_epoch(0).is_ok());
252        assert!(token.verify_epoch(1).is_err());
253    }
254
255    #[test]
256    fn test_verify_epoch_max() {
257        let token = FrameToken::new(FrameId::new(1), 0, 0, u64::MAX);
258        assert!(token.verify_epoch(u64::MAX).is_ok());
259        assert!(token.verify_epoch(u64::MAX - 1).is_err());
260    }
261
262    // ===== Debug 输出格式测试 =====
263
264    #[test]
265    fn test_token_debug_format() {
266        let token = FrameToken::new(FrameId::new(42), 7, 3, 5);
267        let debug_str = format!("{:?}", token);
268        assert!(debug_str.contains("FrameToken"));
269        assert!(debug_str.contains("frame_id"));
270        assert!(debug_str.contains("domain_id"));
271        assert!(debug_str.contains("generation"));
272        assert!(debug_str.contains("epoch"));
273    }
274
275    // ===== FrameId From<u32> trait 测试 =====
276
277    #[test]
278    fn test_frame_id_from_u32_trait() {
279        let id: FrameId = 123u32.into();
280        assert_eq!(id.value(), 123);
281        assert_eq!(id, FrameId::new(123));
282    }
283
284    #[test]
285    fn test_frame_id_from_u32_zero() {
286        let id: FrameId = 0u32.into();
287        assert_eq!(id.value(), 0);
288    }
289
290    #[test]
291    fn test_frame_id_from_u32_max() {
292        let id: FrameId = u32::MAX.into();
293        assert_eq!(id.value(), u32::MAX);
294    }
295
296    // ===== 边界值测试 =====
297
298    #[test]
299    fn test_token_boundary_values() {
300        let token = FrameToken::new(
301            FrameId::new(u32::MAX),
302            u32::MAX,
303            u64::MAX,
304            u64::MAX,
305        );
306        assert_eq!(token.frame_id().value(), u32::MAX);
307        assert_eq!(token.domain_id(), u32::MAX);
308        assert_eq!(token.generation(), u64::MAX);
309        assert_eq!(token.epoch(), u64::MAX);
310    }
311
312    // ===== into_frame_id 测试 =====
313
314    #[test]
315    fn test_into_frame_id_consumes_token() {
316        let token = FrameToken::new(FrameId::new(99), 0, 0, 0);
317        let id = token.into_frame_id();
318        assert_eq!(id, FrameId::new(99));
319    }
320}