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"
generic-array = "0.12"
failure = "0.1"
bitflags = "1.0"
#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)]
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

View File

@ -1,20 +1,21 @@
use crate::durandal::{bin::*, err::*, text::*};
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)?;
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<Face>
fn read_face(b: &[u8]) -> ResultS<Face>
{
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<Face>
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<Face>,
}
#[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<u16> 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, "}}")
}
}

View File

@ -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<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<'_>
{
pub fn new(b: &[u8]) -> ResultS<Wad>
@ -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<ChunkMap>
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