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
//! Reference: https://www.sqlite.org/fileformat2.html
pub mod file_format_version_numbers;
pub mod magic_header_string;
pub mod page_size;
pub mod payload_fractions;
pub mod reserved_bytes_per_page;
use self::{
file_format_version_numbers::FileFormatVersionNumbers, magic_header_string::MagicHeaderString,
page_size::PageSize,
};
use crate::{
header::{payload_fractions::PayloadFractions, reserved_bytes_per_page::ReservedBytesPerPage},
result::SQLiteError,
};
/// # Database File Format
///
/// |Offset | Size | Description|
/// |-------|-------|------------|
/// |0 | 16 | The header string: "SQLite format 3\000" |
/// |16 | 2 | The database page size in bytes. Must be a power of two between 512 and 32768 inclusive, or the value 1 representing a page size of 65536. |
/// |18 | 1 | File format write version. 1 for legacy; 2 for WAL. |
/// |19 | 1 | File format read version. 1 for legacy; 2 for WAL. |
/// |20 | 1 | Bytes of unused "reserved" space at the end of each page. Usually 0. |
/// |21 | 1 | Maximum embedded payload fraction. Must be 64. |
/// |22 | 1 | Minimum embedded payload fraction. Must be 32. |
/// |23 | 1 | Leaf payload fraction. Must be 32. |
/// |24 | 4 | File change counter. |
/// |28 | 4 | Size of the database file in pages. The "in-header database size". |
/// |32 | 4 | Page number of the first freelist trunk page. |
/// |36 | 4 | Total number of freelist pages. |
/// |40 | 4 | The schema cookie. |
/// |44 | 4 | The schema format number. Supported schema formats are 1, 2, 3, and 4. |
/// |48 | 4 | Default page cache size. |
/// |52 | 4 | The page number of the largest root b-tree page when in auto-vacuum or incremental-vacuum modes, or zero otherwise. |
/// |56 | 4 | The database text encoding. A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be. |
/// |60 | 4 | The "user version" as read and set by the user_version pragma. |
/// |64 | 4 | True (non-zero) for incremental-vacuum mode. False (zero) otherwise. |
/// |68 | 4 | The "Application ID" set by PRAGMA application_id. |
/// |72 | 20 | Reserved for expansion. Must be zero. |
/// |92 | 4 | The version-valid-for number. |
/// |96 | 4 | SQLITE_VERSION_NUMBER |
#[derive(Debug)]
pub struct SqliteHeader<'a> {
magic_header_string: MagicHeaderString<'a>,
page_size: PageSize,
file_format_version_numbers: FileFormatVersionNumbers,
reserved_bytes_per_page: ReservedBytesPerPage,
payload_fractions: PayloadFractions,
}
impl<'a> SqliteHeader<'a> {
pub fn magic_header_string(&self) -> &MagicHeaderString<'a> {
&self.magic_header_string
}
pub fn page_size(&self) -> &PageSize {
&self.page_size
}
}
impl<'a> TryFrom<&'a [u8; 100]> for SqliteHeader<'a> {
type Error = SQLiteError;
fn try_from(value: &'a [u8; 100]) -> Result<Self, Self::Error> {
println!("{:x?}", &value[0..=15]);
println!("{:x?}", &value[16..=17]);
println!("{:x?}", &value[18..=19]);
println!("{:x?}", &value[20]);
println!("{:x?}", &value[21..=23]);
let magic_header_string = MagicHeaderString::try_from(&value[0..=15])?;
let page_size = PageSize::try_from(&value[16..=17])?;
let file_format_version_numbers = FileFormatVersionNumbers::try_from(&value[18..=19])?;
let reserved_bytes_per_page = ReservedBytesPerPage::try_from((&page_size, value[20]))?;
let payload_fractions = PayloadFractions::try_from(&value[21..=23])?;
Ok(Self {
magic_header_string,
page_size,
file_format_version_numbers,
reserved_bytes_per_page,
payload_fractions,
})
}
}