Skip to main content

noxu_dbi/
database_id.rs

1//! Database identifier.
2//!
3
4/// Unique identifier for a database.
5///
6///
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
8pub struct DatabaseId(i64);
9
10impl DatabaseId {
11    /// Creates a new DatabaseId.
12    pub fn new(id: i64) -> Self {
13        DatabaseId(id)
14    }
15
16    /// Returns the raw ID value.
17    pub fn id(&self) -> i64 {
18        self.0
19    }
20
21    /// Returns the raw ID value (alias for compatibility).
22    pub fn as_i64(&self) -> i64 {
23        self.0
24    }
25
26    /// Returns the serialized size.
27    ///
28    /// Always 8 bytes (i64 big-endian). uses variable-length packed
29    /// encoding; Noxu uses fixed-size i64 for simplicity and consistency.
30    pub fn log_size(&self) -> usize {
31        8
32    }
33
34    /// Writes this DatabaseId to a log buffer.
35    pub fn write_to_log(&self, buf: &mut Vec<u8>) {
36        buf.extend_from_slice(&self.0.to_be_bytes());
37    }
38
39    /// Reads a DatabaseId from a log buffer.
40    pub fn read_from_log(buf: &[u8]) -> std::io::Result<Self> {
41        if buf.len() < 8 {
42            return Err(std::io::Error::new(
43                std::io::ErrorKind::UnexpectedEof,
44                "buffer too short for DatabaseId",
45            ));
46        }
47        let mut bytes = [0u8; 8];
48        bytes.copy_from_slice(&buf[..8]);
49        Ok(DatabaseId(i64::from_be_bytes(bytes)))
50    }
51}
52
53impl std::fmt::Display for DatabaseId {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(f, "{}", self.0)
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_new_and_id() {
65        let db_id = DatabaseId::new(42);
66        assert_eq!(db_id.id(), 42);
67    }
68
69    #[test]
70    fn test_equality() {
71        let id1 = DatabaseId::new(10);
72        let id2 = DatabaseId::new(10);
73        let id3 = DatabaseId::new(20);
74
75        assert_eq!(id1, id2);
76        assert_ne!(id1, id3);
77    }
78
79    #[test]
80    fn test_hash() {
81        use std::collections::HashSet;
82        let mut set = HashSet::new();
83        set.insert(DatabaseId::new(1));
84        set.insert(DatabaseId::new(1));
85        set.insert(DatabaseId::new(2));
86
87        assert_eq!(set.len(), 2);
88    }
89
90    #[test]
91    fn test_ordering() {
92        let id1 = DatabaseId::new(10);
93        let id2 = DatabaseId::new(20);
94        let id3 = DatabaseId::new(30);
95
96        assert!(id1 < id2);
97        assert!(id2 < id3);
98        assert!(id1 < id3);
99    }
100
101    #[test]
102    fn test_serialization_round_trip() {
103        let original = DatabaseId::new(12345);
104        let mut buf = Vec::new();
105
106        original.write_to_log(&mut buf);
107        assert_eq!(buf.len(), 8);
108
109        let deserialized = DatabaseId::read_from_log(&buf).unwrap();
110        assert_eq!(original, deserialized);
111    }
112
113    #[test]
114    fn test_display() {
115        let db_id = DatabaseId::new(42);
116        assert_eq!(format!("{}", db_id), "42");
117    }
118
119    #[test]
120    fn test_log_size() {
121        let db_id = DatabaseId::new(42);
122        assert_eq!(db_id.log_size(), 8);
123    }
124
125    #[test]
126    fn test_read_from_log_short_buffer() {
127        let buf = vec![0u8; 4]; // Too short
128        let result = DatabaseId::read_from_log(&buf);
129        assert!(result.is_err());
130    }
131}