use crate::grimoire::io::{Mapper, Reader, Writer};
pub const HEADER_SIZE: usize = 16;
#[derive(Default)]
pub struct Header;
impl Header {
#[inline]
pub fn new() -> Self {
Header
}
#[inline]
fn get_header() -> &'static [u8; HEADER_SIZE] {
b"We love Marisa.\0"
}
fn test_header(bytes: &[u8]) -> bool {
if bytes.len() != HEADER_SIZE {
return false;
}
bytes == Self::get_header()
}
pub fn map(&mut self, mapper: &mut Mapper) -> std::io::Result<()> {
let mut buf = [0u8; HEADER_SIZE];
mapper.map_slice(&mut buf)?;
if !Self::test_header(&buf) {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid MARISA header",
));
}
Ok(())
}
pub fn read(&mut self, reader: &mut Reader<'_>) -> std::io::Result<()> {
let mut buf = [0u8; HEADER_SIZE];
reader.read_slice(&mut buf)?;
if !Self::test_header(&buf) {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid MARISA header",
));
}
Ok(())
}
pub fn write(&self, writer: &mut Writer<'_>) -> std::io::Result<()> {
writer.write_slice(Self::get_header())
}
#[inline]
pub fn io_size(&self) -> usize {
HEADER_SIZE
}
pub fn validate(bytes: &[u8]) -> bool {
Self::test_header(bytes)
}
pub fn bytes() -> [u8; HEADER_SIZE] {
*Self::get_header()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_header_new() {
let header = Header::new();
assert_eq!(header.io_size(), HEADER_SIZE);
}
#[test]
fn test_header_size() {
assert_eq!(HEADER_SIZE, 16);
}
#[test]
fn test_header_bytes() {
let bytes = Header::bytes();
assert_eq!(bytes.len(), 16);
assert_eq!(&bytes[..15], b"We love Marisa.");
assert_eq!(bytes[15], 0); }
#[test]
fn test_header_validate_valid() {
let valid_header = b"We love Marisa.\0";
assert!(Header::validate(valid_header));
}
#[test]
fn test_header_validate_invalid_content() {
let invalid_header = b"Invalid header!\0";
assert!(!Header::validate(invalid_header));
}
#[test]
fn test_header_validate_invalid_length() {
let short_header = b"Too short";
assert!(!Header::validate(short_header));
let long_header = b"This header is too long for validation";
assert!(!Header::validate(long_header));
}
#[test]
fn test_header_validate_partial_match() {
let partial = b"We love Marisa.X"; assert!(!Header::validate(partial));
}
#[test]
#[allow(clippy::default_constructed_unit_structs)]
fn test_header_default() {
let header = Header::default();
assert_eq!(header.io_size(), HEADER_SIZE);
}
}