1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
//! The b-tree page header is 8 bytes in size for leaf pages and 12 bytes for
//! interior pages. All multibyte values in the page header are big-endian. The
//! b-tree page header is composed of the following fields:
// TODO:
//
// +---+-------+-----------+-----------+-----------+
// | h . | | | |
// | e . | | | |
// | a . root | page 2 | ... | page N |
// | d . page | | | |
// | e . | | | |
// | r . | | | |
// +---+-------+-----------+-----------+-----------+
// ^ ^ ^
// | page size | page size | page size | page size |
pub mod first_freeblock;
pub mod number_of_cells;
pub mod page_type;
use crate::{
impl_name,
result::{SQLiteError, SQLiteResult},
traits::ParseBytes,
};
use self::{
first_freeblock::BtreePageFirstFreeBlock,
number_of_cells::BtreePageNumberOfCells, page_type::BtreePageType,
};
/// # B-tree Page Header Format (8 Bytes)
///
/// |Offset | Size | Description|
/// |-------|-------|------------|
/// | 0 | 1 | The one-byte flag at offset 0 indicating the b-tree page type. |
/// | 1 | 2 | The two-byte integer at offset 1 gives the start of the first freeblock on the page, or is zero if there are no freeblocks. |
/// | 3 | 2 | The two-byte integer at offset 3 gives the number of cells on the page. |
/// | 5 | 2 | The two-byte integer at offset 5 designates the start of the cell content area. A zero value for this integer is interpreted as 65536. |
/// | 7 | 1 | The one-byte integer at offset 7 gives the number of fragmented free bytes within the cell content area. |
/// | 8 | 4 | The four-byte page number at offset 8 is the right-most pointer. This value appears in the header of interior b-tree pages only and is omitted from all other pages. |
#[derive(Debug, PartialEq, Eq)]
pub struct BtreePageHeader {
page_type: BtreePageType,
first_freeblock: BtreePageFirstFreeBlock,
number_of_cells: BtreePageNumberOfCells,
// btree_header_idx5: u8,
// btree_header_idx6: u8,
// btree_header_idx7: u8,
}
impl BtreePageHeader {
pub fn page_type(&self) -> &BtreePageType {
&self.page_type
}
pub fn first_freeblock(&self) -> &BtreePageFirstFreeBlock {
&self.first_freeblock
}
pub fn number_of_cells(&self) -> &BtreePageNumberOfCells {
&self.number_of_cells
}
}
impl_name! {BtreePageHeader}
impl ParseBytes for BtreePageHeader {
const LENGTH_BYTES: usize = 8;
fn parsing_handler(btree_header: &[u8]) -> SQLiteResult<Self> {
Ok(Self {
page_type: BtreePageType::parse_bytes(&[btree_header[0]])?,
first_freeblock: BtreePageFirstFreeBlock::parse_bytes(&[
btree_header[1],
btree_header[2],
])?,
number_of_cells: BtreePageNumberOfCells::parse_bytes(&[
btree_header[3],
btree_header[4],
])?,
})
}
}
impl TryFrom<&[u8]> for BtreePageHeader {
type Error = SQLiteError;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let parsed = Self::parse_bytes(bytes)?;
// parsed.validate_parsed()?;
Ok(parsed)
}
}