use binrw::{binread, BinRead, BinReaderExt};
use resource_fork::Resource;
pub fn roman_char(input: u8) -> Option<char> {
if input == 0 {
return None;
}
let input = [input];
encoding_rs::MACINTOSH
.decode(&input)
.0
.to_string()
.chars()
.next()
}
#[binread]
#[derive(Debug)]
pub struct LongArray<T: BinRead + 'static>
where
for<'a> <T as BinRead>::Args<'a>: Default + Clone,
{
#[br(temp)]
count: u16,
#[br(count(count))]
pub(crate) items: Vec<T>,
}
pub fn long_list<T: BinRead>(input: LongArray<T>) -> Vec<T>
where
for<'a> <T as BinRead>::Args<'a>: Default + Clone,
{
input.items
}
#[binread]
pub(crate) struct LongArrayPlusOne<T: BinRead + 'static>
where
for<'a> <T as BinRead>::Args<'a>: Default + Clone,
{
#[br(temp)]
last_index: u16,
#[br(temp, calc(if last_index == 0xFFFF { 0 } else {last_index as usize +1} ))]
count: usize,
#[br(count(count))]
pub(crate) items: Vec<T>,
}
pub(crate) fn long_list_plus_one<T: BinRead>(input: LongArrayPlusOne<T>) -> Vec<T>
where
for<'a> <T as BinRead>::Args<'a>: Default + Clone,
{
input.items
}
#[derive(BinRead)]
#[br(import_raw(args: <T as BinRead>::Args<'_>))]
enum ListItem<T: BinRead> {
#[br(magic(0u8))]
None,
Some(#[br(args_raw = args)] T),
}
pub(crate) struct NullTerminatedList<T: BinRead>
where
for<'a> <T as BinRead>::Args<'a>: Clone,
{
items: Vec<T>,
}
impl<T: BinRead> BinRead for NullTerminatedList<T>
where
for<'a> <T as BinRead>::Args<'a>: Clone,
{
type Args<'a> = <T as BinRead>::Args<'a>;
fn read_options<R: std::io::Read + std::io::Seek>(
reader: &mut R,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> binrw::BinResult<Self> {
let mut items = Vec::new();
loop {
match reader.read_type_args::<ListItem<T>>(endian, args.clone())? {
ListItem::None => return Ok(Self { items }),
ListItem::Some(item) => items.push(item),
}
}
}
}
pub(crate) fn null_terminated_list<T: binrw::BinRead>(list: NullTerminatedList<T>) -> Vec<T>
where
for<'a> <T as BinRead>::Args<'a>: Clone,
{
list.items
}
#[binread]
pub(crate) struct LengthPrefixedBuffer {
#[br(temp)]
len: u8,
#[br(count(len))]
contents: Vec<u8>,
}
impl From<LengthPrefixedBuffer> for Vec<u8> {
fn from(val: LengthPrefixedBuffer) -> Self {
val.contents
}
}
#[derive(Debug, Copy, Clone, BinRead, Resource)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[resource(code = "RECT")]
#[br(big)]
pub struct Rect {
pub top: i16,
pub left: i16,
pub bottom: i16,
pub right: i16,
}
impl Rect {
pub fn width(&self) -> i32 {
self.right as i32 - self.left as i32
}
pub fn height(&self) -> i32 {
self.bottom as i32 - self.top as i32
}
}
#[derive(Debug, Copy, Clone, BinRead, Resource)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[resource(code = "PNT ")]
pub struct Point {
pub x: i16,
pub y: i16,
}