#![doc = document_features::document_features!()]
#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
extern crate alloc;
pub use binrw;
#[deprecated(
since = "0.2.3",
note = "Will be removed at the next major release. Use `abootimg_oxide::binrw::io::BufReader` instead."
)]
#[doc(no_inline)]
#[cfg(feature = "std")]
pub use binrw::io::BufReader;
mod standard;
mod vendor;
mod version;
#[binrw::binrw]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[brw(little)]
pub enum EitherHeader {
Standard(
#[br(parse_with = |r, _, ()| Header::parse(r))]
#[bw(write_with = |hdr, w, _, ()| hdr.write(w))]
Header,
),
Vendor(VendorHeader),
}
pub use standard::{Header, HeaderV0, HeaderV0Versioned, HeaderV3};
pub use vendor::{VendorHeader, VendorHeaderV4};
pub use version::{OsPatch, OsVersion, OsVersionPatch};
#[cfg(test)]
mod tests {
use alloc::string::ToString;
use alloc::vec::Vec;
use binrw::{io::Cursor, BinRead};
use super::*;
#[track_caller]
fn check<T: core::fmt::Debug, E: core::fmt::Display>(
res: Result<T, E>,
target_err_msgs: &[&str],
) {
let s = res.unwrap_err().to_string();
for target in target_err_msgs {
assert!(
s.contains(target),
"---\\\n{s}\n\\--- should contain {target:?}"
);
}
}
#[test]
fn invalid_file_signature_either() {
let data = b"aaaaaaaa";
check(
EitherHeader::read(&mut Cursor::new(data)),
&["no variants matched", "bad magic"],
);
}
#[test]
fn invalid_version_either() {
let mut data = Vec::new();
data.extend_from_slice(b"ANDROID!");
data.append(&mut b"aaaa".repeat(8));
data.extend_from_slice(&u32::MAX.to_le_bytes());
data.extend_from_slice(b"aaaa");
data.append(&mut b"a".repeat(16 + 512 + 32 + 1024));
check(
HeaderV0::read(&mut Cursor::new(&data)),
&["invalid header version"],
);
}
#[test]
fn invalid_version_direct_v0() {
let mut data = Vec::new();
data.extend_from_slice(b"ANDROID!");
data.append(&mut b"aaaa".repeat(8));
data.extend_from_slice(&3u32.to_le_bytes());
data.extend_from_slice(b"aaaa");
data.append(&mut b"a".repeat(16 + 512 + 32 + 1024));
check(
HeaderV0::read(&mut Cursor::new(&data)),
&["invalid header version"],
);
}
#[test]
fn invalid_version_direct_v3() {
let mut data = Vec::new();
data.extend_from_slice(b"ANDROID!");
data.append(&mut b"aaaa".repeat(4));
data.append(&mut b"a".repeat(16));
data.extend_from_slice(&0u32.to_le_bytes());
data.append(&mut b"a".repeat(512 + 1024));
check(
HeaderV3::read(&mut Cursor::new(&data)),
&["invalid header version"],
);
}
#[test]
fn invalid_size_direct_v3() {
let mut data = Vec::new();
data.extend_from_slice(b"ANDROID!");
data.append(&mut b"aaaa".repeat(4));
data.append(&mut b"a".repeat(16));
data.extend_from_slice(&3u32.to_le_bytes());
data.append(&mut b"a".repeat(512 + 1024));
check(
HeaderV3::read(&mut Cursor::new(&data)),
&["invalid header size"],
);
}
#[test]
fn invalid_size_either_v3() {
let mut data = Vec::new();
data.extend_from_slice(b"ANDROID!");
data.append(&mut b"aaaa".repeat(4));
data.append(&mut b"a".repeat(16));
data.extend_from_slice(&3u32.to_le_bytes());
data.append(&mut b"a".repeat(512 + 1024));
check(
EitherHeader::read(&mut Cursor::new(&data)),
&["invalid header size"],
);
}
}