Skip to main content

modde_core/
nexus_id.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
6pub enum NexusIdError {
7    #[error("Nexus id cannot be negative: {0}")]
8    Negative(i64),
9    #[error("Nexus id {0} exceeds SQLite INTEGER range")]
10    TooLarge(u64),
11}
12
13macro_rules! nexus_id {
14    ($name:ident) => {
15        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16        #[serde(transparent)]
17        pub struct $name(u64);
18
19        impl $name {
20            #[must_use]
21            pub const fn get(self) -> u64 {
22                self.0
23            }
24
25            pub fn to_i64(self) -> Result<i64, NexusIdError> {
26                i64::try_from(self.0).map_err(|_| NexusIdError::TooLarge(self.0))
27            }
28        }
29
30        impl From<u64> for $name {
31            fn from(value: u64) -> Self {
32                Self(value)
33            }
34        }
35
36        impl TryFrom<i64> for $name {
37            type Error = NexusIdError;
38
39            fn try_from(value: i64) -> Result<Self, Self::Error> {
40                if value < 0 {
41                    return Err(NexusIdError::Negative(value));
42                }
43                Ok(Self(value as u64))
44            }
45        }
46
47        impl fmt::Display for $name {
48            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49                self.0.fmt(f)
50            }
51        }
52    };
53}
54
55nexus_id!(NexusModId);
56nexus_id!(NexusFileId);