From c1ece8b1164f9ea621d5f7d60dc150e1635a8cca Mon Sep 17 00:00:00 2001 From: Marrub Date: Thu, 13 Dec 2018 04:06:57 -0500 Subject: [PATCH] add C repr stuff --- Cargo.toml | 1 + src/durandal/mod.rs | 34 +++++++++++++++- src/marathon/term.rs | 87 ++++++++++++++--------------------------- src/marathon/wad.rs | 92 +++++++++++++++++++++----------------------- 4 files changed, 106 insertions(+), 108 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 46062e0..6760312 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" memmap = "0.6" generic-array = "0.12" failure = "0.1" +bitflags = "1.0" #gtk = "0.4" diff --git a/src/durandal/mod.rs b/src/durandal/mod.rs index 659e95d..106f9a4 100644 --- a/src/durandal/mod.rs +++ b/src/durandal/mod.rs @@ -1,4 +1,4 @@ -//! Library for file reading utilities and mac format utilities. +//! Library for various utilities. #[allow(dead_code)] pub mod bin; @@ -10,4 +10,36 @@ pub mod machead; pub mod pict; 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) + } + } + }; +} + // EOF diff --git a/src/marathon/term.rs b/src/marathon/term.rs index 3903db8..0258c04 100644 --- a/src/marathon/term.rs +++ b/src/marathon/term.rs @@ -1,20 +1,21 @@ use crate::durandal::{bin::*, err::*, text::*}; use std::fmt; -pub fn read_group(b: &[u8], text: &[u8]) -> ResultS +fn read_group(b: &[u8], text: &[u8]) -> ResultS { // flags = b.c_u16b( 0)?; - let ttype = b.c_u16b( 2)?.into(); + let ttype = b.c_u16b( 2)?; let pdata = b.c_i16b( 4)?; let start = b.c_u16b( 6)? as usize; let size = b.c_u16b( 8)? as usize; let lines = b.c_u16b(10)?; let text = mac_roman_conv(&text[start..start+size]); + let ttype = GroupType::from_repr(ttype)?; Ok(Group{ttype, pdata, lines, text}) } -pub fn read_face(b: &[u8]) -> ResultS +fn read_face(b: &[u8]) -> ResultS { let start = b.c_u16b(0)? as usize; let face = b.c_u16b(2)?; @@ -23,7 +24,7 @@ pub fn read_face(b: &[u8]) -> ResultS Ok(Face{start, face, color}) } -pub fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)> +fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)> { const SIZE_GROUP: usize = 12; const SIZE_FACE : usize = 6; @@ -81,6 +82,7 @@ pub struct Terminal faces: Vec, } +#[derive(Debug)] pub struct Face { start: usize, @@ -90,66 +92,33 @@ pub struct Face pub struct Group { - ttype: Type, + ttype: GroupType, pdata: i16, lines: u16, text: String, } -#[derive(Debug)] -pub enum Type -{ - Logon, - Unfinished, - Success, - Failure, - Info, - End, - TeleInter, - TeleIntra, - Checkpoint, - Sound, - Movie, - Track, - Pict, - Logoff, - Camera, - Static, - Tag, -} - -impl From for Type -{ - fn from(n: u16) -> Self +c_enum! { + #[derive(Debug)] + pub enum GroupType: u16 { - match n { - 0 => Type::Logon, - 1 => Type::Unfinished, - 2 => Type::Success, - 3 => Type::Failure, - 4 => Type::Info, - 5 => Type::End, - 6 => Type::TeleInter, - 7 => Type::TeleIntra, - 8 => Type::Checkpoint, - 9 => Type::Sound, - 10 => Type::Movie, - 11 => Type::Track, - 12 => Type::Pict, - 13 => Type::Logoff, - 14 => Type::Camera, - 15 => Type::Static, - 16 => Type::Tag, - _ => panic!("invalid terminal group type {}", n), - } - } -} - -impl fmt::Debug for Face -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result - { - write!(f, "Face{{{} {} {}}}", self.start, self.face, self.color) + 0 => Logon, + 1 => Unfinished, + 2 => Success, + 3 => Failure, + 4 => Info, + 5 => End, + 6 => TeleInter, + 7 => TeleIntra, + 8 => Checkpoint, + 9 => Sound, + 10 => Movie, + 11 => Track, + 12 => Pict, + 13 => Logoff, + 14 => Camera, + 15 => Static, + 16 => Tag, } } @@ -158,7 +127,7 @@ impl fmt::Debug for Group fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?; - if self.text.len() != 0 {write!(f, ";\n{}\n", self.text)?;} + if self.text.len() != 0 {write!(f, ";\n{}", self.text)?;} write!(f, "}}") } } diff --git a/src/marathon/wad.rs b/src/marathon/wad.rs index a3fa9cf..ff5eab1 100644 --- a/src/marathon/wad.rs +++ b/src/marathon/wad.rs @@ -3,45 +3,6 @@ use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv}; use std::{collections::BTreeMap, fmt}; -type Chunk <'a> = &'a[u8]; -type ChunkMap<'a> = BTreeMap>; -type EntryMap<'a> = BTreeMap>; - -pub struct Entry<'a> -{ - pub chunks: ChunkMap<'a>, - pub appdata: &'a[u8], -} - -#[derive(Debug)] -pub struct Wad<'a> -{ - wadver: Ver, - dataver: u16, - origname: String, - appsize: usize, - pub entries: EntryMap<'a>, -} - -#[derive(Debug)] -pub enum Ver -{ - Base, - Dir, - Over, - MI -} - -impl fmt::Debug for Entry<'_> -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result - { - write!(f, "Entry{{ ")?; - for (ident, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(ident))?;} - write!(f, "}}") - } -} - impl Wad<'_> { pub fn new(b: &[u8]) -> ResultS @@ -60,14 +21,7 @@ impl Wad<'_> // entsize = b.c_u16b(82)?; // parent = b.c_u32b(84)?; - let wadver = match wadver { - 4 => Ver::MI, - 2 => Ver::Over, - 1 => Ver::Dir, - 0 => Ver::Base, - _ => return err_msg("invalid Wad version"), - }; - + let wadver = Ver::from_repr(wadver)?; let is_old = match wadver {Ver::Base => true, _ => false}; let entsize = if is_old {8} else {10}; @@ -79,7 +33,7 @@ impl Wad<'_> let size = b.c_u32b(p+4)? as usize; let index = if !is_old {b.c_u16b(p+8)?} else {i as u16}; - if offset + size > b.len() {return err_msg("not enough data for entry")} + if offset + size > b.len() {return err_msg("not enough data for entry");} let chunks = get_chunks(&b[offset..offset+size], is_old)?; let appdata = &b[p+entsize..p+entsize+appsize]; @@ -114,4 +68,46 @@ fn get_chunks(b: &[u8], is_old: bool) -> ResultS Ok(chunks) } +type Chunk <'a> = &'a[u8]; +type ChunkMap<'a> = BTreeMap>; +type EntryMap<'a> = BTreeMap>; + +pub struct Entry<'a> +{ + pub chunks: ChunkMap<'a>, + pub appdata: &'a[u8], +} + +#[derive(Debug)] +pub struct Wad<'a> +{ + wadver: Ver, + dataver: u16, + origname: String, + appsize: usize, + pub entries: EntryMap<'a>, +} + +c_enum! { +#[derive(Debug)] + pub enum Ver: u16 + { + 0 => Base, + 1 => Dir, + 2 => Over, + 4 => MI, + } +} + +impl fmt::Debug for Entry<'_> +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "Entry{{ ")?; + for (ident, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(ident))?;} + if self.appdata.len() != 0{write!(f, "\nappdata: {:?} ", self.appdata)?;} + write!(f, "}}") + } +} + // EOF