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