add C repr stuff

png-branch
an 2018-12-13 04:06:57 -05:00
parent a3e9dde0ff
commit c1ece8b116
4 changed files with 106 additions and 108 deletions

View File

@ -8,4 +8,5 @@ edition = "2018"
memmap = "0.6" memmap = "0.6"
generic-array = "0.12" generic-array = "0.12"
failure = "0.1" failure = "0.1"
bitflags = "1.0"
#gtk = "0.4" #gtk = "0.4"

View File

@ -1,4 +1,4 @@
//! Library for file reading utilities and mac format utilities. //! Library for various utilities.
#[allow(dead_code)] #[allow(dead_code)]
pub mod bin; pub mod bin;
@ -10,4 +10,36 @@ pub mod machead;
pub mod pict; pub mod pict;
pub mod text; 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 // EOF

View File

@ -1,20 +1,21 @@
use crate::durandal::{bin::*, err::*, text::*}; use crate::durandal::{bin::*, err::*, text::*};
use std::fmt; use std::fmt;
pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group> fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{ {
// flags = b.c_u16b( 0)?; // 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 pdata = b.c_i16b( 4)?;
let start = b.c_u16b( 6)? as usize; let start = b.c_u16b( 6)? as usize;
let size = b.c_u16b( 8)? as usize; let size = b.c_u16b( 8)? as usize;
let lines = b.c_u16b(10)?; let lines = b.c_u16b(10)?;
let text = mac_roman_conv(&text[start..start+size]); let text = mac_roman_conv(&text[start..start+size]);
let ttype = GroupType::from_repr(ttype)?;
Ok(Group{ttype, pdata, lines, text}) Ok(Group{ttype, pdata, lines, text})
} }
pub fn read_face(b: &[u8]) -> ResultS<Face> fn read_face(b: &[u8]) -> ResultS<Face>
{ {
let start = b.c_u16b(0)? as usize; let start = b.c_u16b(0)? as usize;
let face = b.c_u16b(2)?; let face = b.c_u16b(2)?;
@ -23,7 +24,7 @@ pub fn read_face(b: &[u8]) -> ResultS<Face>
Ok(Face{start, face, color}) 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_GROUP: usize = 12;
const SIZE_FACE : usize = 6; const SIZE_FACE : usize = 6;
@ -81,6 +82,7 @@ pub struct Terminal
faces: Vec<Face>, faces: Vec<Face>,
} }
#[derive(Debug)]
pub struct Face pub struct Face
{ {
start: usize, start: usize,
@ -90,66 +92,33 @@ pub struct Face
pub struct Group pub struct Group
{ {
ttype: Type, ttype: GroupType,
pdata: i16, pdata: i16,
lines: u16, lines: u16,
text: String, text: String,
} }
#[derive(Debug)] c_enum! {
pub enum Type #[derive(Debug)]
{ pub enum GroupType: u16
Logon,
Unfinished,
Success,
Failure,
Info,
End,
TeleInter,
TeleIntra,
Checkpoint,
Sound,
Movie,
Track,
Pict,
Logoff,
Camera,
Static,
Tag,
}
impl From<u16> for Type
{
fn from(n: u16) -> Self
{ {
match n { 0 => Logon,
0 => Type::Logon, 1 => Unfinished,
1 => Type::Unfinished, 2 => Success,
2 => Type::Success, 3 => Failure,
3 => Type::Failure, 4 => Info,
4 => Type::Info, 5 => End,
5 => Type::End, 6 => TeleInter,
6 => Type::TeleInter, 7 => TeleIntra,
7 => Type::TeleIntra, 8 => Checkpoint,
8 => Type::Checkpoint, 9 => Sound,
9 => Type::Sound, 10 => Movie,
10 => Type::Movie, 11 => Track,
11 => Type::Track, 12 => Pict,
12 => Type::Pict, 13 => Logoff,
13 => Type::Logoff, 14 => Camera,
14 => Type::Camera, 15 => Static,
15 => Type::Static, 16 => Tag,
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)
} }
} }
@ -158,7 +127,7 @@ impl fmt::Debug for Group
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{ {
write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?; 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, "}}") write!(f, "}}")
} }
} }

View File

@ -3,45 +3,6 @@
use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv}; use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv};
use std::{collections::BTreeMap, fmt}; use std::{collections::BTreeMap, fmt};
type Chunk <'a> = &'a[u8];
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
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<'_> impl Wad<'_>
{ {
pub fn new(b: &[u8]) -> ResultS<Wad> pub fn new(b: &[u8]) -> ResultS<Wad>
@ -60,14 +21,7 @@ impl Wad<'_>
// entsize = b.c_u16b(82)?; // entsize = b.c_u16b(82)?;
// parent = b.c_u32b(84)?; // parent = b.c_u32b(84)?;
let wadver = match wadver { let wadver = Ver::from_repr(wadver)?;
4 => Ver::MI,
2 => Ver::Over,
1 => Ver::Dir,
0 => Ver::Base,
_ => return err_msg("invalid Wad version"),
};
let is_old = match wadver {Ver::Base => true, _ => false}; let is_old = match wadver {Ver::Base => true, _ => false};
let entsize = if is_old {8} else {10}; let entsize = if is_old {8} else {10};
@ -79,7 +33,7 @@ impl Wad<'_>
let size = b.c_u32b(p+4)? as usize; let size = b.c_u32b(p+4)? as usize;
let index = if !is_old {b.c_u16b(p+8)?} else {i as u16}; 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 chunks = get_chunks(&b[offset..offset+size], is_old)?;
let appdata = &b[p+entsize..p+entsize+appsize]; let appdata = &b[p+entsize..p+entsize+appsize];
@ -114,4 +68,46 @@ fn get_chunks(b: &[u8], is_old: bool) -> ResultS<ChunkMap>
Ok(chunks) Ok(chunks)
} }
type Chunk <'a> = &'a[u8];
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
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 // EOF