From 24c3ccc680645efe528d9be018b6565634532265 Mon Sep 17 00:00:00 2001 From: Marrub Date: Tue, 5 Feb 2019 04:28:13 -0500 Subject: [PATCH] better C enum handling and organization --- src/durandal/cenum.rs | 68 +++++++++++++++++++ src/durandal/err.rs | 20 ++++++ src/durandal/mod.rs | 36 +--------- src/durandal/traits.rs | 17 +++++ src/main.rs | 4 +- .../machead.rs => marathon/machdr.rs} | 0 src/marathon/mod.rs | 1 + src/marathon/pict.rs | 2 +- src/marathon/wad.rs | 5 +- 9 files changed, 114 insertions(+), 39 deletions(-) create mode 100644 src/durandal/cenum.rs create mode 100644 src/durandal/traits.rs rename src/{durandal/machead.rs => marathon/machdr.rs} (100%) diff --git a/src/durandal/cenum.rs b/src/durandal/cenum.rs new file mode 100644 index 0000000..440961f --- /dev/null +++ b/src/durandal/cenum.rs @@ -0,0 +1,68 @@ +//! C representation enumerations. + +/// Creates an enumeration and function for converting a representation into +/// the enumeration type. +#[macro_export] +macro_rules! c_enum +{ + ( + $(#[$outer:meta])* + pub enum $E:ident: $T:ty + { + $($value:expr => $Enum:ident,)+ + } + ) => { + $(#[$outer])* + pub enum $E + { + $($Enum,)+ + } + + impl $E + { + pub fn from_repr(n: $T) -> Result<$E, ReprError<$T>> + { + match n { + $($value => Ok($E::$Enum),)+ + n => Err(ReprError(n)) + } + } + } + }; +} + +#[cfg(test)] +mod test +{ + use crate::durandal::err::ReprError; + + c_enum! { + #[derive(Debug, PartialEq)] + pub enum TestEnum: u16 + { + 0 => Zero, + 1 => One, + 2 => Two, + } + } + + #[test] + fn c_enum_should_be_ok() + { + assert_eq!(TestEnum::from_repr(0), Ok(TestEnum::Zero)); + assert_eq!(TestEnum::from_repr(1), Ok(TestEnum::One)); + assert_eq!(TestEnum::from_repr(2), Ok(TestEnum::Two)); + assert_eq!(TestEnum::from_repr(3), Err(ReprError(3))); + assert_eq!(TestEnum::from_repr(4), Err(ReprError(4))); + assert_eq!(TestEnum::from_repr(5), Err(ReprError(5))); + } + + #[test] + #[should_panic] + fn c_enum_should_error() + { + TestEnum::from_repr(3).unwrap(); + } +} + +// EOF diff --git a/src/durandal/err.rs b/src/durandal/err.rs index 09e52a3..8fb0396 100644 --- a/src/durandal/err.rs +++ b/src/durandal/err.rs @@ -2,6 +2,26 @@ pub use failure::{Error, Fail, format_err}; +use crate::durandal::traits::PrimInt; +use std::fmt; + +#[derive(PartialEq)] +pub struct ReprError(pub T) where T: PrimInt; + +impl Fail for ReprError where T: PrimInt {} + +impl fmt::Display for ReprError where T: PrimInt +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + {write!(f, "representation error (got {})", self.0)} +} + +impl fmt::Debug for ReprError where T: PrimInt +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + {fmt::Display::fmt(self, f)} +} + pub type ResultS = Result; pub fn err_msg(s: &'static str) -> ResultS {Err(failure::err_msg(s))} diff --git a/src/durandal/mod.rs b/src/durandal/mod.rs index 6dd1ac0..ae1e662 100644 --- a/src/durandal/mod.rs +++ b/src/durandal/mod.rs @@ -2,44 +2,14 @@ #[allow(dead_code)] pub mod bin; +#[macro_use] +pub mod cenum; pub mod chunk; pub mod crc; pub mod err; pub mod fx32; pub mod image; -pub mod machead; pub mod text; - -/// Creates an enumeration and function for converting a representation into -/// the enumeration type. -#[macro_export] -macro_rules! c_enum -{ - ( - $(#[$outer:meta])* - pub enum $E:ident: $T:ty - { - $($value:expr => $Enum:ident,)+ - } - ) => { - $(#[$outer])* - pub enum $E - { - $($Enum,)+ - } - - impl $E - { - pub fn from_repr(n: $T) -> ResultS<$E> - { - let t = match n { - $($value => $E::$Enum,)+ - n => return Err(format_err!("invalid representation for {} (got {})", stringify!($E), n)) - }; - Ok(t) - } - } - }; -} +pub mod traits; // EOF diff --git a/src/durandal/traits.rs b/src/durandal/traits.rs new file mode 100644 index 0000000..5d6b84b --- /dev/null +++ b/src/durandal/traits.rs @@ -0,0 +1,17 @@ +//! Traits for basic types, because Rust doesn't provide them. + +/// Any primitive integer type. +pub trait PrimInt: 'static + Send + Sync + std::fmt::Display + PartialEq {} + +impl PrimInt for u8 {} +impl PrimInt for i8 {} +impl PrimInt for u16 {} +impl PrimInt for i16 {} +impl PrimInt for u32 {} +impl PrimInt for i32 {} +impl PrimInt for u64 {} +impl PrimInt for i64 {} +impl PrimInt for u128 {} +impl PrimInt for i128 {} + +// EOF diff --git a/src/main.rs b/src/main.rs index 2818567..319efa4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use maraiah::durandal::{chunk::*, err::*, image::Image}; -use maraiah::marathon::{map, pict, term, wad}; +use maraiah::marathon::{machdr, map, pict, term, wad}; use memmap::Mmap; use std::{io, io::Write, fs, env}; @@ -25,7 +25,7 @@ fn main() -> ResultS<()> let arg = env::args().nth(1).expect("need at least 1 argument"); let fp = fs::File::open(arg)?; let mm = unsafe{Mmap::map(&fp)?}; - let wad = wad::Wad::new(&mm)?; + let wad = wad::Wad::new(&mm[machdr::try_mac_header(&mm)..])?; println!("{:#?}", wad); diff --git a/src/durandal/machead.rs b/src/marathon/machdr.rs similarity index 100% rename from src/durandal/machead.rs rename to src/marathon/machdr.rs diff --git a/src/marathon/mod.rs b/src/marathon/mod.rs index 525bd09..44818b8 100644 --- a/src/marathon/mod.rs +++ b/src/marathon/mod.rs @@ -1,5 +1,6 @@ //! Library for file data formats. +pub mod machdr; pub mod map; pub mod pict; pub mod term; diff --git a/src/marathon/pict.rs b/src/marathon/pict.rs index 7e5a953..ab94c4f 100644 --- a/src/marathon/pict.rs +++ b/src/marathon/pict.rs @@ -148,7 +148,7 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re /// Process a CompressedQuickTime operation. pub fn read_quicktime_c(_im: Image, _b: &[u8]) -> ResultS { - err_msg("compressed quicktime format not implemented") + unimplemented!() } /// Load a PICT image. diff --git a/src/marathon/wad.rs b/src/marathon/wad.rs index 5fbbb23..cd61da4 100644 --- a/src/marathon/wad.rs +++ b/src/marathon/wad.rs @@ -1,13 +1,12 @@ //! Marathon Wad format handling. -use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv}; +use crate::durandal::{bin::*, err::*, text::mac_roman_conv}; use std::{collections::BTreeMap, fmt}; impl Wad<'_> { pub fn new(b: &[u8]) -> ResultS { - let b = &b[try_mac_header(b)..]; if b.len() < 128 {return err_msg("not enough data for Wad header");} let wadver = b.c_u16b( 0)?; @@ -89,7 +88,7 @@ pub struct Wad<'a> } c_enum! { -#[derive(Debug)] + #[derive(Debug)] pub enum Ver: u16 { 0 => Base,