1use std::fmt;
50
51#[derive(
67 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
68)]
69pub struct FileId(pub u64);
70
71impl FileId {
72 #[must_use]
74 pub const fn new(id: u64) -> Self {
75 Self(id)
76 }
77
78 #[must_use]
80 pub fn random() -> Self {
81 Self(rand::random())
82 }
83
84 #[must_use]
86 pub const fn as_u64(self) -> u64 {
87 self.0
88 }
89}
90
91impl fmt::Display for FileId {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 write!(f, "0x{:016x}", self.0)
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
110pub struct AuthorId(pub u64);
111
112impl AuthorId {
113 #[must_use]
115 pub const fn new(id: u64) -> Self {
116 Self(id)
117 }
118
119 #[must_use]
121 pub const fn as_u64(self) -> u64 {
122 self.0
123 }
124}
125
126impl fmt::Display for AuthorId {
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 write!(f, "{}", self.0)
129 }
130}
131
132#[derive(
149 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
150)]
151pub struct VersionNumber(pub u64);
152
153impl VersionNumber {
154 pub const GENESIS: Self = Self(1);
156
157 pub fn next(self) -> crate::Result<Self> {
163 self.0
164 .checked_add(1)
165 .map(Self)
166 .ok_or(crate::AionError::VersionOverflow { max: self.0 })
167 }
168
169 #[must_use]
171 pub const fn as_u64(self) -> u64 {
172 self.0
173 }
174}
175
176impl fmt::Display for VersionNumber {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 write!(f, "{}", self.0)
179 }
180}
181
182pub type Hash = [u8; 32];
184
185pub type PublicKey = [u8; 32];
187
188pub type Signature = [u8; 64];
190
191#[cfg(test)]
192#[allow(clippy::unwrap_used)] mod tests {
194 use super::*;
195
196 mod file_id {
197 use super::*;
198
199 #[test]
200 fn should_create_file_id_from_u64() {
201 let id = FileId::new(42);
202 assert_eq!(id.as_u64(), 42);
203 }
204
205 #[test]
206 fn should_generate_random_file_id() {
207 let id1 = FileId::random();
208 let id2 = FileId::random();
209 assert_ne!(id1, id2);
211 }
212
213 #[test]
214 fn should_display_as_hex() {
215 let id = FileId::new(255);
216 assert_eq!(format!("{id}"), "0x00000000000000ff");
217 }
218
219 #[test]
220 fn should_serialize_deserialize() {
221 let id = FileId::new(12345);
222 let json = serde_json::to_string(&id).unwrap();
224 let deserialized: FileId = serde_json::from_str(&json).unwrap();
225 assert_eq!(id, deserialized);
226 }
227
228 #[test]
229 fn should_be_comparable() {
230 let id1 = FileId::new(1);
231 let id2 = FileId::new(2);
232 assert!(id1 < id2);
233 assert!(id2 > id1);
234 }
235
236 #[test]
237 fn should_be_hashable() {
238 use std::collections::HashSet;
239 let mut set = HashSet::new();
240 set.insert(FileId::new(1));
241 set.insert(FileId::new(2));
242 set.insert(FileId::new(1)); assert_eq!(set.len(), 2);
244 }
245 }
246
247 mod author_id {
248 use super::*;
249
250 #[test]
251 fn should_create_author_id_from_u64() {
252 let id = AuthorId::new(100);
253 assert_eq!(id.as_u64(), 100);
254 }
255
256 #[test]
257 fn should_display_as_decimal() {
258 let id = AuthorId::new(42);
259 assert_eq!(format!("{id}"), "42");
260 }
261
262 #[test]
263 fn should_serialize_deserialize() {
264 let id = AuthorId::new(999);
265 let json = serde_json::to_string(&id).unwrap();
267 let deserialized: AuthorId = serde_json::from_str(&json).unwrap();
268 assert_eq!(id, deserialized);
269 }
270
271 #[test]
272 fn should_be_comparable() {
273 let id1 = AuthorId::new(1);
274 let id2 = AuthorId::new(1);
275 assert_eq!(id1, id2);
276 }
277 }
278
279 mod version_number {
280 use super::*;
281
282 #[test]
283 fn should_have_genesis_constant() {
284 assert_eq!(VersionNumber::GENESIS.as_u64(), 1);
285 }
286
287 #[test]
288 fn should_increment_version() {
289 let v1 = VersionNumber::GENESIS;
290 let v2 = v1.next().unwrap();
291 assert_eq!(v2.as_u64(), 2);
292
293 let v3 = v2.next().unwrap();
294 assert_eq!(v3.as_u64(), 3);
295 }
296
297 #[test]
298 fn should_handle_overflow() {
299 let v_max = VersionNumber(u64::MAX);
300 let result = v_max.next();
301 assert!(result.is_err());
302 }
303
304 #[test]
305 fn should_display_as_decimal() {
306 let v = VersionNumber(42);
307 assert_eq!(format!("{v}"), "42");
308 }
309
310 #[test]
311 fn should_serialize_deserialize() {
312 let v = VersionNumber(123);
313 let json = serde_json::to_string(&v).unwrap();
315 let deserialized: VersionNumber = serde_json::from_str(&json).unwrap();
316 assert_eq!(v, deserialized);
317 }
318
319 #[test]
320 fn should_be_ordered() {
321 let v1 = VersionNumber(1);
322 let v2 = VersionNumber(2);
323 let v3 = VersionNumber(3);
324
325 assert!(v1 < v2);
326 assert!(v2 < v3);
327 assert!(v1 < v3);
328 }
329
330 #[test]
331 fn should_sort_correctly() {
332 let mut versions = [VersionNumber(3), VersionNumber(1), VersionNumber(2)];
333 versions.sort();
334 assert_eq!(versions.first().unwrap().as_u64(), 1);
335 assert_eq!(versions.get(1).unwrap().as_u64(), 2);
336 assert_eq!(versions.get(2).unwrap().as_u64(), 3);
337 }
338 }
339
340 mod type_aliases {
341 use super::*;
342
343 #[test]
344 fn hash_should_be_32_bytes() {
345 let hash: Hash = [0u8; 32];
346 assert_eq!(hash.len(), 32);
347 }
348
349 #[test]
350 fn public_key_should_be_32_bytes() {
351 let pk: PublicKey = [0u8; 32];
352 assert_eq!(pk.len(), 32);
353 }
354
355 #[test]
356 fn signature_should_be_64_bytes() {
357 let sig: Signature = [0u8; 64];
358 assert_eq!(sig.len(), 64);
359 }
360 }
361}