assembly_fdb_core/
file.rs

1#![allow(clippy::upper_case_acronyms)]
2//! The structures, as they are serialized
3//!
4//! This module contains the low-level structs that make up the FDB file. These
5//! structures are annotated with `#[repr(C)]` and can be used to read directly
6//! from a memory-mapped file on a little-endian machine.
7//!
8//! Not all values of these structs are valid for FDB files, but all well-formed
9//! FDB-files can be represented by these values. Most importantly, the
10//! [`FDBColumnHeader::column_data_type`] only has a limited amount of defined values but
11//! covers the whole 32 bits.
12
13#[cfg(feature = "bytemuck")]
14use bytemuck_derive::{Pod, Zeroable};
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
18#[repr(C)]
19/// The basic format of an array reference
20pub struct ArrayHeader {
21    /// The number of entries in the array
22    pub count: u32,
23    /// The offset of the start of the array
24    pub base_offset: u32,
25}
26
27impl From<(u32, u32)> for ArrayHeader {
28    fn from((count, base_offset): (u32, u32)) -> Self {
29        Self { count, base_offset }
30    }
31}
32
33/// The header of the database file.
34///
35/// This struct exists only once at index 0 of the file.
36#[derive(Copy, Clone, Debug, PartialEq, Eq)]
37#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
38#[repr(C)]
39pub struct FDBHeader {
40    /// The [`FDBTableHeader`] array.
41    pub tables: ArrayHeader,
42}
43
44impl FDBHeader {
45    #[inline]
46    /// Returns the length in bytes of the TableHeader array.
47    pub const fn table_headers_byte_count(&self) -> usize {
48        self.tables.count as usize * std::mem::size_of::<FDBTableHeader>()
49    }
50}
51
52#[derive(Copy, Clone, Debug, PartialEq, Eq)]
53#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
54#[repr(C)]
55/// The header of a table.
56///
57/// This struct is used in the global TableHeader list and contains
58/// the offsets of the two structures that define the definition and
59/// content of the tables.
60pub struct FDBTableHeader {
61    /// The offset of this table definition header.
62    pub table_def_header_addr: u32,
63    /// The offset of the table data header.
64    pub table_data_header_addr: u32,
65}
66
67#[derive(Copy, Clone, Debug, PartialEq, Eq)]
68#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
69#[repr(C)]
70/// The header of a table definition
71///
72/// This struct exists once per table and contains links to information
73/// on the name of the table and the names and data types of the columns.
74pub struct FDBTableDefHeader {
75    /// The number of columns in this table.
76    pub column_count: u32,
77    /// The offset of the (null-terminated) name of this table
78    pub table_name_addr: u32,
79    /// The offset of the array of [`FDBColumnHeader`]s
80    pub column_header_list_addr: u32,
81}
82
83impl From<(u32, u32, u32)> for FDBTableDefHeader {
84    fn from((column_count, table_name_addr, column_header_list_addr): (u32, u32, u32)) -> Self {
85        Self {
86            column_count,
87            table_name_addr,
88            column_header_list_addr,
89        }
90    }
91}
92
93impl From<[u32; 3]> for FDBTableDefHeader {
94    fn from([column_count, table_name_addr, column_header_list_addr]: [u32; 3]) -> Self {
95        Self {
96            column_count,
97            table_name_addr,
98            column_header_list_addr,
99        }
100    }
101}
102
103impl FDBTableDefHeader {
104    #[inline]
105    /// Returns the expected byte length of the referenced [`FDBColumnHeader`] array.
106    pub const fn column_header_list_byte_count(&self) -> usize {
107        self.column_count as usize * std::mem::size_of::<FDBColumnHeader>()
108    }
109}
110
111#[derive(Copy, Clone, Debug, PartialEq, Eq)]
112#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
113#[repr(C)]
114/// The header of a column (field-of-row) definition
115///
116/// This struct contains information on the name and data type of a column.
117/// It is always an element of the array pointed to by the [`FDBTableDefHeader`].
118pub struct FDBColumnHeader {
119    /// The numeric identifier of the data type.
120    pub column_data_type: u32,
121    /// The offset of the (null-terminated) name.
122    pub column_name_addr: u32,
123}
124
125#[derive(Copy, Clone, Debug, PartialEq, Eq)]
126#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
127#[repr(C)]
128/// The header of a table data block
129///
130/// It contains a reference to the array of buckets that hold the row data.
131pub struct FDBTableDataHeader {
132    /// The buckets.
133    pub buckets: ArrayHeader,
134}
135
136impl FDBTableDataHeader {
137    #[inline]
138    /// Returns the expected byte length of the [`FDBBucketHeader`] array.
139    pub const fn bucket_header_list_byte_count(&self) -> usize {
140        self.buckets.count as usize * std::mem::size_of::<FDBBucketHeader>()
141    }
142}
143
144#[derive(Copy, Clone, Debug, PartialEq, Eq)]
145#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
146#[repr(C)]
147/// The header of a single bucket.
148///
149/// A bucket is a linked list of references to rows that all have the same
150/// primary key hash.
151pub struct FDBBucketHeader {
152    /// Offset of the first element of the linked list or 0xffffffff.
153    pub row_header_list_head_addr: u32,
154}
155
156impl From<u32> for FDBBucketHeader {
157    fn from(row_header_list_head_addr: u32) -> Self {
158        Self {
159            row_header_list_head_addr,
160        }
161    }
162}
163
164#[derive(Copy, Clone, Debug, PartialEq, Eq)]
165#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
166#[repr(C)]
167/// One entry of the linked list of references to rows.
168///
169/// This struct always contains a reference to a row and may
170/// point to another entry in the linked list.
171pub struct FDBRowHeaderListEntry {
172    /// The offset of the row header.
173    pub row_header_addr: u32,
174    /// The offset of the next list entry or `0`.
175    pub row_header_list_next_addr: u32,
176}
177
178#[derive(Copy, Clone, Debug, PartialEq, Eq)]
179#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
180#[repr(C)]
181/// The header for a single row
182pub struct FDBRowHeader {
183    /// The fields in this row
184    pub fields: ArrayHeader,
185}
186
187impl FDBRowHeader {
188    #[inline]
189    /// Returns the expected byte length of the [`FDBFieldData`] array.
190    pub const fn field_data_list_byte_count(&self) -> usize {
191        self.fields.count as usize * std::mem::size_of::<FDBFieldData>()
192    }
193}
194
195#[derive(Copy, Clone, Debug, PartialEq, Eq)]
196#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
197#[repr(C)]
198/// The type and value of a row field.
199pub struct FDBFieldData {
200    /// The data type.
201    pub data_type: u32,
202    /// The bytes that specify the value.
203    pub value: [u8; 4],
204}
205
206#[cfg(test)]
207mod tests {
208    use super::*;
209    use std::mem;
210
211    #[test]
212    fn test_align() {
213        assert_eq!(mem::align_of::<FDBHeader>(), 4);
214        assert_eq!(mem::align_of::<FDBTableHeader>(), 4);
215        assert_eq!(mem::align_of::<FDBTableDefHeader>(), 4);
216        assert_eq!(mem::align_of::<FDBColumnHeader>(), 4);
217        assert_eq!(mem::align_of::<FDBTableDataHeader>(), 4);
218        assert_eq!(mem::align_of::<FDBBucketHeader>(), 4);
219        assert_eq!(mem::align_of::<FDBRowHeaderListEntry>(), 4);
220        assert_eq!(mem::align_of::<FDBRowHeader>(), 4);
221        assert_eq!(mem::align_of::<FDBFieldData>(), 4);
222    }
223
224    #[test]
225    fn test_size_of() {
226        assert_eq!(mem::size_of::<FDBHeader>(), 8);
227        assert_eq!(mem::size_of::<FDBTableHeader>(), 8);
228        assert_eq!(mem::size_of::<FDBTableDefHeader>(), 12);
229        assert_eq!(mem::size_of::<FDBColumnHeader>(), 8);
230        assert_eq!(mem::size_of::<FDBTableDataHeader>(), 8);
231        assert_eq!(mem::size_of::<FDBBucketHeader>(), 4);
232        assert_eq!(mem::size_of::<FDBRowHeaderListEntry>(), 8);
233        assert_eq!(mem::size_of::<FDBRowHeader>(), 8);
234        assert_eq!(mem::size_of::<FDBFieldData>(), 8);
235    }
236}