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
10const 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#[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 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}