better C enum handling and organization

png-branch
an 2019-02-05 04:28:13 -05:00
parent 4c590a0dc2
commit 24c3ccc680
9 changed files with 114 additions and 39 deletions

68
src/durandal/cenum.rs Normal file
View File

@ -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

View File

@ -2,6 +2,26 @@
pub use failure::{Error, Fail, format_err};
use crate::durandal::traits::PrimInt;
use std::fmt;
#[derive(PartialEq)]
pub struct ReprError<T>(pub T) where T: PrimInt;
impl<T> Fail for ReprError<T> where T: PrimInt {}
impl<T> fmt::Display for ReprError<T> where T: PrimInt
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{write!(f, "representation error (got {})", self.0)}
}
impl<T> fmt::Debug for ReprError<T> where T: PrimInt
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{fmt::Display::fmt(self, f)}
}
pub type ResultS<T> = Result<T, Error>;
pub fn err_msg<T>(s: &'static str) -> ResultS<T> {Err(failure::err_msg(s))}

View File

@ -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

17
src/durandal/traits.rs Normal file
View File

@ -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

View File

@ -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);

View File

@ -1,5 +1,6 @@
//! Library for file data formats.
pub mod machdr;
pub mod map;
pub mod pict;
pub mod term;

View File

@ -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<Image>
{
err_msg("compressed quicktime format not implemented")
unimplemented!()
}
/// Load a PICT image.

View File

@ -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<Wad>
{
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,