aria2_gid/
lib.rs

1//! # Aria2-Gid
2//!
3//! [![GitHub last commit](https://img.shields.io/github/last-commit/share121/aria2-gid/master)](https://github.com/share121/aria2-gid/commits/master)
4//! [![Test](https://github.com/share121/aria2-gid/workflows/Test/badge.svg)](https://github.com/share121/aria2-gid/actions)
5//! [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/share121/aria2-gid/blob/master/LICENSE)
6//!
7//! Aria2-Gid 是一个用于生成和解析 Aria2 GID 的库。
8//!
9//! GID 是一个 64 位无符号整数,由两部分组成:
10//! - 高 32 位:UNIX 时间戳(秒级)
11//! - 低 32 位:随机数
12//!
13//! # 示例
14//!
15//! ```rust
16//! use aria2_gid::Gid;
17//!
18//! // 生成新的 GID
19//! let gid = Gid::new();
20//! println!("新生成的 GID: {}", gid);
21//!
22//! // 从十六进制字符串解析
23//! let hex_gid: Gid = "5f9a3b801a4c3d2e".parse().unwrap();
24//! println!("解析的 GID: {}", hex_gid);
25//!
26//! // 获取时间戳和随机数部分
27//! println!("时间戳: {}", gid.timestamp());
28//! println!("随机数: {}", gid.random());
29//! ```
30
31use std::time::{Duration, SystemTime, UNIX_EPOCH};
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
34pub struct Gid(u64);
35
36impl Gid {
37    pub fn new() -> Self {
38        let timestamp = SystemTime::now()
39            .duration_since(UNIX_EPOCH)
40            .expect("Time went backwards");
41        Self::from_duration(timestamp)
42    }
43    pub fn from_duration(timestamp: Duration) -> Self {
44        let timestamp = timestamp.as_secs();
45        let random_num: u32 = rand::random();
46        Gid(timestamp << 32 | random_num as u64)
47    }
48    pub fn timestamp(&self) -> u32 {
49        (self.0 >> 32) as u32
50    }
51    pub fn random(&self) -> u32 {
52        self.0 as u32
53    }
54    pub fn to_hex_string(&self) -> String {
55        format!("{:08x}{:08x}", self.timestamp(), self.random())
56    }
57    pub fn from_hex_string(s: &str) -> Option<Self> {
58        if s.len() != 16 {
59            return None;
60        }
61        let timestamp = u32::from_str_radix(&s[..8], 16).ok()? as u64;
62        let random = u32::from_str_radix(&s[8..], 16).ok()? as u64;
63        Some(Gid(timestamp << 32 | random))
64    }
65}
66
67impl std::fmt::Display for Gid {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        write!(f, "{}", self.to_hex_string())
70    }
71}
72
73impl std::str::FromStr for Gid {
74    type Err = &'static str;
75    fn from_str(s: &str) -> Result<Self, Self::Err> {
76        Gid::from_hex_string(s).ok_or("Invalid GID format")
77    }
78}
79
80impl Default for Gid {
81    fn default() -> Self {
82        Self::new()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_gid_new() {
92        let gid1 = Gid::new();
93        let gid2 = Gid::new();
94        assert_ne!(gid1, gid2);
95        let timestamp1 = gid1.timestamp();
96        let timestamp2 = gid2.timestamp();
97        assert!(timestamp2 >= timestamp1);
98        assert!(timestamp2 - timestamp1 <= 1);
99    }
100
101    #[test]
102    fn test_gid_from_duration() {
103        let duration = Duration::from_secs(1234567890);
104        let gid = Gid::from_duration(duration);
105        assert_eq!(gid.timestamp(), 1234567890);
106    }
107
108    #[test]
109    fn test_gid_timestamp_and_random() {
110        let timestamp = 1672531200; // 2023-01-01 00:00:00 UTC
111        let random_val = 0x12345678;
112        let gid = Gid((timestamp as u64) << 32 | random_val as u64);
113        assert_eq!(gid.timestamp(), timestamp);
114        assert_eq!(gid.random(), random_val);
115    }
116
117    #[test]
118    fn test_gid_to_hex_string() {
119        let gid = Gid(0x1234567890ABCDEF);
120        let hex_string = gid.to_hex_string();
121        assert_eq!(hex_string, "1234567890abcdef");
122    }
123
124    #[test]
125    fn test_gid_from_hex_string() {
126        // 有效的情况
127        let hex_string = "1234567890abcdef";
128        let gid = Gid::from_hex_string(hex_string).unwrap();
129        assert_eq!(gid.timestamp(), 0x12345678);
130        assert_eq!(gid.random(), 0x90ABCDEF);
131
132        // 无效的情况
133        assert!(Gid::from_hex_string("").is_none()); // 空字符串
134        assert!(Gid::from_hex_string("123").is_none()); // 太短
135        assert!(Gid::from_hex_string("1234567890abcdef123").is_none()); // 太长
136        assert!(Gid::from_hex_string("gggggggggggggggg").is_none()); // 无效字符
137    }
138}