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
use std::io::Read;
use crate::{Magic, Version};
/// Check if the provided item looks like a WEBC file.
///
/// This function is a quick check to make sure the provided source has the WEBC
/// magic a version number, and will **not** do any expensive parsing or
/// validation.
///
/// ```rust
/// assert!(webc::is_webc(b"\0webc002"));
/// ```
///
/// This is just a specialised version of [`detect()`].
pub fn is_webc(reader: &[u8]) -> bool {
detect(reader).is_ok()
}
/// Check whether something looks like a valid WEBC file and extract its
/// version number.
///
/// This will *not* apply any validation or check that the rest of the file
/// is correct.
///
/// # Examples
///
/// ```rust
/// # use webc::Version;
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let buffer = b"\0webc002";
/// let version = webc::detect(&buffer[..])?;
/// assert_eq!(version, Version::V2);
/// # Ok(())
/// # }
/// ```
pub fn detect(mut reader: impl Read) -> Result<Version, DetectError> {
let mut magic: Magic = [0; 5];
reader.read_exact(&mut magic)?;
if magic != crate::MAGIC {
return Err(DetectError::InvalidMagic {
found: magic,
expected: crate::MAGIC,
});
}
let mut version = Version([0; 3]);
reader.read_exact(&mut version.0)?;
Ok(version)
}
/// An error returned by [`detect()`].
#[derive(Debug, thiserror::Error)]
pub enum DetectError {
/// An error occurred while reading.
#[error(transparent)]
Io(#[from] std::io::Error),
/// The [`Magic`] bytes were invalid.
#[error(
"Expected the magic bytes to be \"{}\", but found \"{}\"",
expected.escape_ascii(),
found.escape_ascii(),
)]
InvalidMagic {
/// The [`Magic`] bytes the file started with.
found: Magic,
/// The [`Magic`] bytes that were expected.
expected: Magic,
},
}