61 lines
1.9 KiB
Rust
61 lines
1.9 KiB
Rust
use crate::error::Error;
|
|
use std::convert::{TryFrom, TryInto};
|
|
|
|
static HEADER_STRING: &[u8] = &[
|
|
//S q l i t e ` ` f o r m a t ` ` 3 \u{0}
|
|
83, 81, 76, 105, 116, 101, 32, 102, 111, 114, 109, 97, 116, 32, 51, 0,
|
|
];
|
|
|
|
/// This struct will wrap our 32bit number allowing us
|
|
/// to control how it gets used later.
|
|
#[derive(Debug)]
|
|
pub struct PageSize(u32);
|
|
|
|
impl TryFrom<u16> for PageSize {
|
|
type Error = Error;
|
|
|
|
fn try_from(v: u16) -> Result<PageSize, Self::Error> {
|
|
match v {
|
|
// Special case for the largest page size
|
|
1 => Ok(PageSize(65_536u32)),
|
|
|
|
// < 512, != 1
|
|
0 | 2..=511 => Err(Error::InvalidPageSize(format!(
|
|
"value must be >= 512, found: {}",
|
|
v
|
|
))),
|
|
|
|
_ => {
|
|
if v.is_power_of_two() {
|
|
Ok(PageSize(v as u32))
|
|
} else {
|
|
Err(Error::InvalidPageSize(format!(
|
|
"value must be a power of 2, found: {}",
|
|
v
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Validate that the bytes provided match the special string
|
|
/// at the start of Sqlite3 files
|
|
pub fn validate_magic_string(bytes: &[u8]) -> Result<(), Error> {
|
|
let buf = &bytes[0..16];
|
|
if buf != HEADER_STRING {
|
|
return Err(Error::HeaderString(String::from_utf8_lossy(buf).to_string()));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Attempt to generate the appropriate `PageSize` struct
|
|
pub fn parse_page_size(bytes: &[u8]) -> Result<PageSize, Error> {
|
|
// Convert into array, and convert error if needed, so that the `?` operator works
|
|
let page_size_bytes: [u8; 2] = bytes[16..18].try_into().map_err(|_| {
|
|
Error::InvalidPageSize(format!("expected a 2 byte slice, found: {:?}", bytes))
|
|
})?;
|
|
|
|
u16::from_be_bytes(page_size_bytes).try_into()
|
|
} |