umadb_core/
node.rs

1use crate::events_tree_nodes::{EventInternalNode, EventLeafNode, EventOverflowNode};
2use crate::free_lists_tree_nodes::{
3    FreeListInternalNode, FreeListLeafNode, FreeListTsnInternalNode, FreeListTsnLeafNode,
4};
5use crate::header_node::HeaderNode;
6use crate::tags_tree_nodes::{TagInternalNode, TagLeafNode, TagsInternalNode, TagsLeafNode};
7use umadb_dcb::{DCBError, DCBResult};
8
9// Constants for serialization
10const PAGE_TYPE_HEADER: u8 = b'1';
11const PAGE_TYPE_FREELIST_LEAF: u8 = b'2';
12const PAGE_TYPE_FREELIST_INTERNAL: u8 = b'3';
13const PAGE_TYPE_EVENT_LEAF: u8 = b'4';
14const PAGE_TYPE_EVENT_INTERNAL: u8 = b'5';
15const PAGE_TYPE_TAGS_LEAF: u8 = b'6';
16const PAGE_TYPE_TAGS_INTERNAL: u8 = b'7';
17const PAGE_TYPE_TAG_LEAF: u8 = b'8';
18const PAGE_TYPE_TAG_INTERNAL: u8 = b'9';
19const PAGE_TYPE_EVENT_OVERFLOW: u8 = b'a';
20const PAGE_TYPE_FREELIST_TSN_LEAF: u8 = b'b';
21const PAGE_TYPE_FREELIST_TSN_INTERNAL: u8 = b'c';
22
23// Enum to represent different node types
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum Node {
26    Header(HeaderNode),
27    FreeListLeaf(FreeListLeafNode),
28    FreeListInternal(FreeListInternalNode),
29    EventLeaf(EventLeafNode),
30    EventInternal(EventInternalNode),
31    EventOverflow(EventOverflowNode),
32    TagsLeaf(TagsLeafNode),
33    TagsInternal(TagsInternalNode),
34    TagLeaf(TagLeafNode),
35    TagInternal(TagInternalNode),
36    FreeListTsnLeaf(FreeListTsnLeafNode),
37    FreeListTsnInternal(FreeListTsnInternalNode),
38}
39
40impl Node {
41    pub fn get_type_byte(&self) -> u8 {
42        match self {
43            Node::Header(_) => PAGE_TYPE_HEADER,
44            Node::FreeListLeaf(_) => PAGE_TYPE_FREELIST_LEAF,
45            Node::FreeListInternal(_) => PAGE_TYPE_FREELIST_INTERNAL,
46            Node::EventLeaf(_) => PAGE_TYPE_EVENT_LEAF,
47            Node::EventInternal(_) => PAGE_TYPE_EVENT_INTERNAL,
48            Node::EventOverflow(_) => PAGE_TYPE_EVENT_OVERFLOW,
49            Node::TagsLeaf(_) => PAGE_TYPE_TAGS_LEAF,
50            Node::TagsInternal(_) => PAGE_TYPE_TAGS_INTERNAL,
51            Node::TagLeaf(_) => PAGE_TYPE_TAG_LEAF,
52            Node::TagInternal(_) => PAGE_TYPE_TAG_INTERNAL,
53            Node::FreeListTsnLeaf(_) => PAGE_TYPE_FREELIST_TSN_LEAF,
54            Node::FreeListTsnInternal(_) => PAGE_TYPE_FREELIST_TSN_INTERNAL,
55        }
56    }
57
58    pub fn type_name(&self) -> &'static str {
59        match self {
60            Node::Header(_) => "Header",
61            Node::FreeListLeaf(_) => "FreeListLeaf",
62            Node::FreeListInternal(_) => "FreeListInternal",
63            Node::EventLeaf(_) => "EventLeaf",
64            Node::EventInternal(_) => "EventInternal",
65            Node::EventOverflow(_) => "EventOverflow",
66            Node::TagsLeaf(_) => "TagsLeaf",
67            Node::TagsInternal(_) => "TagsInternal",
68            Node::TagLeaf(_) => "TagLeaf",
69            Node::TagInternal(_) => "TagInternal",
70            Node::FreeListTsnLeaf(_) => "FreeListTsnLeaf",
71            Node::FreeListTsnInternal(_) => "FreeListTsnInternal",
72        }
73    }
74
75    pub fn calc_serialized_size(&self) -> usize {
76        match self {
77            Node::Header(_) => 48, // HeaderNode has a fixed size of 48 bytes (includes root_tags_tree_id and next_position)
78            Node::FreeListLeaf(node) => node.calc_serialized_size(),
79            Node::FreeListInternal(node) => node.calc_serialized_size(),
80            Node::EventLeaf(node) => node.calc_serialized_size(),
81            Node::EventInternal(node) => node.calc_serialized_size(),
82            Node::EventOverflow(node) => node.calc_serialized_size(),
83            Node::TagsLeaf(node) => node.calc_serialized_size(),
84            Node::TagsInternal(node) => node.calc_serialized_size(),
85            Node::TagLeaf(node) => node.calc_serialized_size(),
86            Node::TagInternal(node) => node.calc_serialized_size(),
87            Node::FreeListTsnLeaf(node) => node.calc_serialized_size(),
88            Node::FreeListTsnInternal(node) => node.calc_serialized_size(),
89        }
90    }
91
92    /// No-allocation serialization into a provided buffer slice.
93    /// Returns the number of bytes written.
94    /// Implemented for key node types; for others it falls back to allocate-and-copy.
95    pub fn serialize_into(&self, buf: &mut [u8]) -> DCBResult<usize> {
96        match self {
97            Node::Header(node) => {
98                let n = node.serialize_into(buf);
99                Ok(n)
100            }
101            Node::FreeListLeaf(node) => {
102                let n = node.serialize_into(buf);
103                Ok(n)
104            }
105            Node::FreeListInternal(node) => {
106                let n = node.serialize_into(buf);
107                Ok(n)
108            }
109            Node::EventLeaf(node) => {
110                let n = node.serialize_into(buf);
111                Ok(n)
112            }
113            Node::EventInternal(node) => {
114                let n = node.serialize_into(buf)?;
115                Ok(n)
116            }
117            Node::EventOverflow(node) => {
118                let n = node.serialize_into(buf);
119                Ok(n)
120            }
121            Node::TagsLeaf(node) => {
122                let n = node.serialize_into(buf);
123                Ok(n)
124            }
125            Node::TagsInternal(node) => {
126                let n = node.serialize_into(buf);
127                Ok(n)
128            }
129            Node::TagLeaf(node) => {
130                let n = node.serialize_into(buf);
131                Ok(n)
132            }
133            Node::TagInternal(node) => {
134                let n = node.serialize_into(buf);
135                Ok(n)
136            }
137            Node::FreeListTsnLeaf(node) => {
138                let n = node.serialize_into(buf);
139                Ok(n)
140            }
141            Node::FreeListTsnInternal(node) => {
142                let n = node.serialize_into(buf);
143                Ok(n)
144            }
145        }
146    }
147
148    pub fn deserialize(node_type: u8, data: &[u8]) -> DCBResult<Self> {
149        match node_type {
150            PAGE_TYPE_HEADER => {
151                let node = HeaderNode::from_slice(data)?;
152                Ok(Node::Header(node))
153            }
154            PAGE_TYPE_FREELIST_LEAF => {
155                let node = FreeListLeafNode::from_slice(data)?;
156                Ok(Node::FreeListLeaf(node))
157            }
158            PAGE_TYPE_FREELIST_INTERNAL => {
159                let node = FreeListInternalNode::from_slice(data)?;
160                Ok(Node::FreeListInternal(node))
161            }
162            PAGE_TYPE_EVENT_LEAF => {
163                let node = EventLeafNode::from_slice(data)?;
164                Ok(Node::EventLeaf(node))
165            }
166            PAGE_TYPE_EVENT_INTERNAL => {
167                let node = EventInternalNode::from_slice(data)?;
168                Ok(Node::EventInternal(node))
169            }
170            PAGE_TYPE_EVENT_OVERFLOW => {
171                let node = EventOverflowNode::from_slice(data)?;
172                Ok(Node::EventOverflow(node))
173            }
174            PAGE_TYPE_TAGS_LEAF => {
175                let node = TagsLeafNode::from_slice(data)?;
176                Ok(Node::TagsLeaf(node))
177            }
178            PAGE_TYPE_TAGS_INTERNAL => {
179                let node = TagsInternalNode::from_slice(data)?;
180                Ok(Node::TagsInternal(node))
181            }
182            PAGE_TYPE_TAG_LEAF => {
183                let node = TagLeafNode::from_slice(data)?;
184                Ok(Node::TagLeaf(node))
185            }
186            PAGE_TYPE_TAG_INTERNAL => {
187                let node = TagInternalNode::from_slice(data)?;
188                Ok(Node::TagInternal(node))
189            }
190            PAGE_TYPE_FREELIST_TSN_LEAF => {
191                let node = FreeListTsnLeafNode::from_slice(data)?;
192                Ok(Node::FreeListTsnLeaf(node))
193            }
194            PAGE_TYPE_FREELIST_TSN_INTERNAL => {
195                let node = FreeListTsnInternalNode::from_slice(data)?;
196                Ok(Node::FreeListTsnInternal(node))
197            }
198            _ => Err(DCBError::DatabaseCorrupted(format!(
199                "Invalid node type: {node_type}"
200            ))),
201        }
202    }
203}