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
use core::ops::Deref;
use super::ParseBytes;
/// # In-header database size
/// The in-header database size is a 4-byte big-endian integer at offset 28
/// into the header stores the size of the database file in pages. If this
/// in-header datasize size is not valid (see the next paragraph), then the
/// database size is computed by looking at the actual size of the database
/// file. Older versions of SQLite ignored the in-header database size and used
/// the actual file size exclusively. Newer versions of SQLite use the in-header
/// database size if it is available but fall back to the actual file size if
/// the in-header database size is not valid.
///
/// The in-header database size is only considered to be valid if it is
/// non-zero and if the 4-byte change counter at offset 24 exactly matches the
/// 4-byte version-valid-for number at offset 92. The in-header database size is
/// always valid when the database is only modified using recent versions of
/// SQLite, versions 3.7.0 (2010-07-21) and later. If a legacy version of SQLite
/// writes to the database, it will not know to update the in-header database
/// size and so the in-header database size could be incorrect. But legacy
/// versions of SQLite will also leave the version-valid-for number at offset 92
/// unchanged so it will not match the change-counter. Hence, invalid in-header
/// database sizes can be detected (and ignored) by observing when the
/// change-counter does not match the version-valid-for number.
#[derive(Debug)]
pub struct DatabaseFileSizeInPages(u32);
impl DatabaseFileSizeInPages {
pub fn get(&self) -> u32 {
self.0
}
}
impl Deref for DatabaseFileSizeInPages {
type Target = u32;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ParseBytes<&[u8]> for DatabaseFileSizeInPages {
fn struct_name() -> &'static str {
"DatabaseFileSizeInPages"
}
fn bytes_length() -> usize {
4
}
fn parsing_handler(bytes: &[u8]) -> crate::result::SQLiteResult<Self> {
let buf: [u8; 4] = bytes.try_into()?;
let database_size = u32::from_be_bytes(buf);
Ok(Self(database_size))
}
}