1use std::fmt;
2use std::str::FromStr;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
6pub struct GameId(i64);
7
8impl GameId {
9 pub const fn new(id: i64) -> Self {
11 Self(id)
12 }
13
14 pub const fn as_i64(&self) -> i64 {
16 self.0
17 }
18}
19
20impl From<i64> for GameId {
21 fn from(id: i64) -> Self {
22 Self(id)
23 }
24}
25
26impl From<GameId> for i64 {
27 fn from(id: GameId) -> i64 {
28 id.0
29 }
30}
31
32impl fmt::Display for GameId {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "{}", self.0)
35 }
36}
37
38impl FromStr for GameId {
39 type Err = std::num::ParseIntError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 Ok(Self(s.parse()?))
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use std::collections::{HashMap, HashSet};
50
51 #[test]
52 fn test_game_id_new() {
53 let id = GameId::new(2023020001);
54 assert_eq!(id.as_i64(), 2023020001);
55 }
56
57 #[test]
58 fn test_game_id_new_negative() {
59 let id = GameId::new(-1);
60 assert_eq!(id.as_i64(), -1);
61 }
62
63 #[test]
64 fn test_game_id_new_zero() {
65 let id = GameId::new(0);
66 assert_eq!(id.as_i64(), 0);
67 }
68
69 #[test]
70 fn test_game_id_as_i64() {
71 let id = GameId::new(12345);
72 assert_eq!(id.as_i64(), 12345);
73 }
74
75 #[test]
76 fn test_game_id_to_string() {
77 let id = GameId::new(2023020001);
78 assert_eq!(id.to_string(), "2023020001");
79
80 let negative_id = GameId::new(-42);
81 assert_eq!(negative_id.to_string(), "-42");
82 }
83
84 #[test]
85 fn test_game_id_from_i64() {
86 let id: GameId = 2023020001_i64.into();
87 assert_eq!(id.as_i64(), 2023020001);
88
89 let id2 = GameId::from(9876543210_i64);
90 assert_eq!(id2.as_i64(), 9876543210);
91 }
92
93 #[test]
94 fn test_i64_from_game_id() {
95 let id = GameId::new(2023020001);
96 let value: i64 = id.into();
97 assert_eq!(value, 2023020001);
98 }
99
100 #[test]
101 fn test_game_id_display() {
102 let id = GameId::new(2024030405);
103 assert_eq!(format!("{}", id), "2024030405");
104
105 let negative_id = GameId::new(-123);
106 assert_eq!(format!("{}", negative_id), "-123");
107 }
108
109 #[test]
110 fn test_game_id_from_str() {
111 let id = GameId::from_str("2023020001").unwrap();
112 assert_eq!(id.as_i64(), 2023020001);
113
114 let id2: GameId = "9876543210".parse().unwrap();
115 assert_eq!(id2.as_i64(), 9876543210);
116
117 let negative_id: GameId = "-42".parse().unwrap();
118 assert_eq!(negative_id.as_i64(), -42);
119 }
120
121 #[test]
122 fn test_game_id_from_str_invalid() {
123 assert!(GameId::from_str("not-a-number").is_err());
125 assert!(GameId::from_str("abc123").is_err());
126 assert!(GameId::from_str("").is_err());
127
128 assert!(GameId::from_str("12.34").is_err());
130 assert!(GameId::from_str("12 34").is_err());
131
132 assert!(GameId::from_str("999999999999999999999999999").is_err());
134 }
135
136 #[test]
137 fn test_game_id_equality() {
138 let id1 = GameId::new(2023020001);
139 let id2 = GameId::new(2023020001);
140 let id3 = GameId::new(2023020002);
141
142 assert_eq!(id1, id2);
143 assert_ne!(id1, id3);
144 assert_ne!(id2, id3);
145 }
146
147 #[test]
148 fn test_game_id_ordering() {
149 let id1 = GameId::new(100);
150 let id2 = GameId::new(200);
151 let id3 = GameId::new(200);
152
153 assert!(id1 < id2);
154 assert!(id2 > id1);
155 assert!(id2 <= id3);
156 assert!(id2 >= id3);
157 assert_eq!(id2.cmp(&id3), std::cmp::Ordering::Equal);
158 assert_eq!(id1.cmp(&id2), std::cmp::Ordering::Less);
159 assert_eq!(id2.cmp(&id1), std::cmp::Ordering::Greater);
160 }
161
162 #[test]
163 fn test_game_id_ordering_negative() {
164 let id1 = GameId::new(-100);
165 let id2 = GameId::new(0);
166 let id3 = GameId::new(100);
167
168 assert!(id1 < id2);
169 assert!(id2 < id3);
170 assert!(id1 < id3);
171 }
172
173 #[test]
174 fn test_game_id_hash() {
175 let mut set = HashSet::new();
176 let id1 = GameId::new(2023020001);
177 let id2 = GameId::new(2023020001);
178 let id3 = GameId::new(2023020002);
179
180 set.insert(id1);
181 assert!(set.contains(&id2)); assert!(!set.contains(&id3));
183
184 set.insert(id3);
185 assert_eq!(set.len(), 2);
186 }
187
188 #[test]
189 fn test_game_id_as_map_key() {
190 let mut map = HashMap::new();
191 let id1 = GameId::new(2023020001);
192 let id2 = GameId::new(2023020002);
193
194 map.insert(id1, "Game 1");
195 map.insert(id2, "Game 2");
196
197 assert_eq!(map.get(&id1), Some(&"Game 1"));
198 assert_eq!(map.get(&id2), Some(&"Game 2"));
199 assert_eq!(map.get(&GameId::new(2023020001)), Some(&"Game 1"));
200 }
201
202 #[test]
203 fn test_game_id_const() {
204 const GAME_ID: GameId = GameId::new(2023020001);
205 assert_eq!(GAME_ID.as_i64(), 2023020001);
206 }
207
208 #[test]
209 fn test_game_id_copy_clone() {
210 let id1 = GameId::new(2023020001);
211 let id2 = id1; let id3 = id1; assert_eq!(id1, id2);
215 assert_eq!(id1, id3);
216 assert_eq!(id2, id3);
217 }
218}