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,
    },
}