1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct IdError {
7 kind: &'static str,
8}
9
10impl IdError {
11 const fn empty(kind: &'static str) -> Self {
12 Self { kind }
13 }
14}
15
16impl fmt::Display for IdError {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 write!(f, "{} cannot be empty", self.kind)
19 }
20}
21
22impl std::error::Error for IdError {}
23
24macro_rules! id_type {
25 ($name:ident) => {
26 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
27 pub struct $name(String);
28
29 impl $name {
30 pub fn new(value: impl Into<String>) -> Result<Self, IdError> {
31 let value = value.into();
32 if value.trim().is_empty() {
33 return Err(IdError::empty(stringify!($name)));
34 }
35 Ok(Self(value))
36 }
37
38 #[must_use]
39 pub fn as_str(&self) -> &str {
40 &self.0
41 }
42 }
43
44 impl fmt::Display for $name {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 f.write_str(&self.0)
47 }
48 }
49 };
50}
51
52id_type!(ActorId);
53id_type!(FactEventId);
54id_type!(FactId);
55id_type!(EvidenceId);
56id_type!(SourceId);
57
58#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
59pub struct TimestampMillis(i64);
60
61impl TimestampMillis {
62 #[must_use]
63 pub const fn from_unix_millis(value: i64) -> Self {
64 Self(value)
65 }
66
67 #[must_use]
68 pub const fn as_unix_millis(self) -> i64 {
69 self.0
70 }
71}