use std::io::{Read, Write};
use anyhow::Result;
use crate::resource::prp::PlasmaRead;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct LoadMask {
pub quality_lo: u8,
pub quality_hi: u8,
}
impl LoadMask {
pub const ALWAYS: LoadMask = LoadMask {
quality_lo: 0xFF,
quality_hi: 0xFF,
};
pub const NEVER: LoadMask = LoadMask {
quality_lo: 0,
quality_hi: 0,
};
pub fn from_byte(byte: u8) -> Self {
Self {
quality_lo: ((byte & 0xF0) >> 4) | 0xF0,
quality_hi: (byte & 0x0F) | 0xF0,
}
}
pub fn new(quality_lo: u8, quality_hi: u8) -> Self {
Self {
quality_lo,
quality_hi,
}
}
pub fn from_packed(byte: u8) -> Self {
Self {
quality_lo: ((byte & 0xF0) >> 4) | 0xF0,
quality_hi: (byte & 0x0F) | 0xF0,
}
}
pub fn is_used(&self) -> bool {
self.quality_lo != 0xFF || self.quality_hi != 0xFF
}
pub fn never_loads(&self) -> bool {
self.quality_lo == 0 && self.quality_hi == 0
}
pub fn read(reader: &mut impl Read) -> Result<Self> {
let byte = reader.read_u8()?;
let quality_lo = ((byte & 0xF0) >> 4) | 0xF0;
let quality_hi = (byte & 0x0F) | 0xF0;
Ok(Self {
quality_lo,
quality_hi,
})
}
pub fn write(&self, writer: &mut impl Write) -> Result<()> {
let byte = (self.quality_lo << 4) | (self.quality_hi & 0x0F);
writer.write_all(&[byte])?;
Ok(())
}
}
impl Default for LoadMask {
fn default() -> Self {
Self::ALWAYS
}
}
impl std::fmt::Debug for LoadMask {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if *self == Self::ALWAYS {
write!(f, "LoadMask(Always)")
} else {
write!(
f,
"LoadMask(lo:{:#04x} hi:{:#04x})",
self.quality_lo, self.quality_hi
)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_always() {
let m = LoadMask::ALWAYS;
assert!(!m.is_used());
assert!(!m.never_loads());
}
#[test]
fn test_never() {
let m = LoadMask::NEVER;
assert!(m.is_used());
assert!(m.never_loads());
}
#[test]
fn test_round_trip() {
let m = LoadMask::new(0xF3, 0xF5);
let mut buf = Vec::new();
m.write(&mut buf).unwrap();
assert_eq!(buf.len(), 1);
let mut cursor = Cursor::new(&buf);
let m2 = LoadMask::read(&mut cursor).unwrap();
assert_eq!(m, m2);
}
#[test]
fn test_always_round_trip() {
let m = LoadMask::ALWAYS;
let mut buf = Vec::new();
m.write(&mut buf).unwrap();
let mut cursor = Cursor::new(&buf);
let m2 = LoadMask::read(&mut cursor).unwrap();
assert_eq!(m, m2);
}
}