add new error handling

png-branch
an 2018-12-11 03:08:23 -05:00
parent 932ec1a668
commit f0212fe162
8 changed files with 38 additions and 27 deletions

View File

@ -7,4 +7,5 @@ edition = "2018"
[dependencies] [dependencies]
memmap = "0.6" memmap = "0.6"
generic-array = "0.12" generic-array = "0.12"
failure = "0.1"
#gtk = "0.4" #gtk = "0.4"

View File

@ -1,8 +1,8 @@
//! Binary data conversion utilities. //! Binary data conversion utilities.
pub type Ident = [u8; 4]; use crate::durandal::err::*;
pub type ResultS<T> = Result<T, &'static str>; pub type Ident = [u8; 4];
pub trait BinUtil pub trait BinUtil
{ {
@ -35,19 +35,19 @@ impl BinUtil for [u8]
{ {
fn c_iden(&self, i: usize) -> ResultS<Ident> fn c_iden(&self, i: usize) -> ResultS<Ident>
{ {
if i + 3 >= self.len() {return Err("not enough data")} if i + 3 >= self.len() {return err_msg("not enough data")}
Ok([self[i], self[i+1], self[i+2], self[i+3]]) Ok([self[i], self[i+1], self[i+2], self[i+3]])
} }
fn c_u32b(&self, i: usize) -> ResultS<u32> fn c_u32b(&self, i: usize) -> ResultS<u32>
{ {
if i + 3 >= self.len() {return Err("not enough data")} if i + 3 >= self.len() {return err_msg("not enough data")}
Ok(u32::from_be_bytes([self[i], self[i+1], self[i+2], self[i+3]])) Ok(u32::from_be_bytes([self[i], self[i+1], self[i+2], self[i+3]]))
} }
fn c_u16b(&self, i: usize) -> ResultS<u16> fn c_u16b(&self, i: usize) -> ResultS<u16>
{ {
if i + 1 >= self.len() {return Err("not enough data")} if i + 1 >= self.len() {return err_msg("not enough data")}
Ok(u16::from_be_bytes([self[i], self[i+1]])) Ok(u16::from_be_bytes([self[i], self[i+1]]))
} }
} }

9
src/durandal/err.rs Normal file
View File

@ -0,0 +1,9 @@
//! Error handling.
pub use failure::{Error, Fail};
pub type ResultS<T> = Result<T, Error>;
pub fn err_msg<T>(s: &'static str) -> ResultS<T> {Err(failure::err_msg(s))}
// EOF

View File

@ -3,6 +3,7 @@
#[allow(dead_code)] #[allow(dead_code)]
pub mod bin; pub mod bin;
pub mod crc; pub mod crc;
pub mod err;
pub mod image; pub mod image;
pub mod machead; pub mod machead;
pub mod pict; pub mod pict;

View File

@ -1,6 +1,6 @@
//! QuickDraw PICT format loader. //! QuickDraw PICT format loader.
use crate::durandal::{bin::*, image::*}; use crate::durandal::{bin::*, err::*, image::*};
use generic_array::*; use generic_array::*;
const PACK_DEFAULT: u16 = 0; const PACK_DEFAULT: u16 = 0;
@ -66,7 +66,7 @@ fn read_rle(b: &[u8], pt: usize, ln: bool) -> ResultS<(Vec<u8>, usize)>
} }
if o.len() == pt {Ok((o, p))} if o.len() == pt {Ok((o, p))}
else {Err("incorrect size for compressed scanline")} else {err_msg("incorrect size for compressed scanline")}
} }
/// Expand packed pixel data based on bit depth. /// Expand packed pixel data based on bit depth.
@ -76,7 +76,7 @@ fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
4 => b.len() * 2, 4 => b.len() * 2,
2 => b.len() * 4, 2 => b.len() * 4,
1 => b.len() * 8, 1 => b.len() * 8,
_ => return Err("invalid bit depth") _ => return err_msg("invalid bit depth")
}); });
for ch in b { for ch in b {
@ -84,7 +84,7 @@ fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
4 => for i in 1..=0 {o.push(ch >> i * 4 & 0xfu8)}, // 2 nibbles 4 => for i in 1..=0 {o.push(ch >> i * 4 & 0xfu8)}, // 2 nibbles
2 => for i in 3..=0 {o.push(ch >> i * 2 & 0x3u8)}, // 4 dibits 2 => for i in 3..=0 {o.push(ch >> i * 2 & 0x3u8)}, // 4 dibits
1 => for i in 7..=0 {o.push(ch >> i * 1 & 0x1u8)}, // 8 bits 1 => for i in 7..=0 {o.push(ch >> i * 1 & 0x1u8)}, // 8 bits
_ => return Err("invalid bit depth") _ => return err_msg("invalid bit depth")
} }
} }
@ -118,8 +118,8 @@ fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Result
p += 46; // size of header p += 46; // size of header
if pf & 0x8000 == 0 {return Err("PICT1 not supported")} if pf & 0x8000 == 0 {return err_msg("PICT1 not supported")}
if xe - xb != w || ye - yb != h {return Err("image bounds are incorrect")} if xe - xb != w || ye - yb != h {return err_msg("image bounds are incorrect")}
let map = if packed {get_clut(&b[p..])?} else {Vec::new()}; let map = if packed {get_clut(&b[p..])?} else {Vec::new()};
@ -156,7 +156,7 @@ fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Result
Ok(im) Ok(im)
} }
else {Err("invalid configuration")}, else {err_msg("invalid configuration")},
16 => 16 =>
if pt < 8 || pack == PACK_NONE { if pt < 8 || pack == PACK_NONE {
// uncompressed R5G5B5 // uncompressed R5G5B5
@ -179,7 +179,7 @@ fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Result
Ok(im) Ok(im)
} }
else {Err("invalid configuration")}, else {err_msg("invalid configuration")},
32 => 32 =>
if pt < 8 || pack == PACK_NONE || pack == PACK_NOPAD { if pt < 8 || pack == PACK_NONE || pack == PACK_NOPAD {
// uncompressed RGB8 or XRGB8 // uncompressed RGB8 or XRGB8
@ -209,14 +209,14 @@ fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Result
Ok(im) Ok(im)
} }
else {Err("invalid configuration")}, else {err_msg("invalid configuration")},
_ => Err("invalid bit depth") _ => err_msg("invalid bit depth")
} }
} }
/// Process a CompressedQuickTime operation. /// Process a CompressedQuickTime operation.
fn read_quicktime_c(_im: Image, _b: &[u8]) -> ResultS<Image> fn read_quicktime_c(_im: Image, _b: &[u8]) -> ResultS<Image>
{Err("compressed quicktime format not implemented")} {err_msg("compressed quicktime format not implemented")}
/// Load a PICT image. /// Load a PICT image.
pub fn load_pict(b: &[u8]) -> ResultS<Image> pub fn load_pict(b: &[u8]) -> ResultS<Image>
@ -289,11 +289,11 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image>
0x00a1 => p += (b.c_u16b(p+2)? & !1) as usize + 2, // LongComment 0x00a1 => p += (b.c_u16b(p+2)? & !1) as usize + 2, // LongComment
0x100..= 0x100..=
0x7fff => p += (op >> 8) as usize * 2, // Reserved 0x7fff => p += (op >> 8) as usize * 2, // Reserved
_ => return Err("invalid op in PICT") _ => return err_msg("invalid op in PICT")
} }
} }
Err("no image in data") err_msg("no image in data")
} }
// EOF // EOF

View File

@ -1,7 +1,7 @@
pub mod durandal; pub mod durandal;
pub mod marathon; pub mod marathon;
use crate::durandal::{bin::ResultS, image::Image, pict::load_pict}; use crate::durandal::{err::*, image::Image, pict::load_pict};
use crate::marathon::{wad, term}; use crate::marathon::{wad, term};
use memmap::Mmap; use memmap::Mmap;
use std::{io, io::Write, fs, env}; use std::{io, io::Write, fs, env};
@ -25,7 +25,7 @@ impl Minf
use crate::durandal::text::mac_roman_conv; use crate::durandal::text::mac_roman_conv;
use crate::durandal::bin::*; use crate::durandal::bin::*;
if b.len() < 88 {return Err("not enough data for Minf")} if b.len() < 88 {return err_msg("not enough data for Minf")}
let env_code = b.c_u16b( 0)?; let env_code = b.c_u16b( 0)?;
let physi_id = b.c_u16b( 2)?; let physi_id = b.c_u16b( 2)?;
@ -56,12 +56,12 @@ fn write_ppm(fname: &str, im: &Image) -> io::Result<()>
Ok(()) Ok(())
} }
fn main() -> io::Result<()> fn main() -> ResultS<()>
{ {
let arg = env::args().nth(1).expect("need at least 1 argument"); let arg = env::args().nth(1).expect("need at least 1 argument");
let fp = fs::File::open(arg)?; let fp = fs::File::open(arg)?;
let mm = unsafe{Mmap::map(&fp)?}; let mm = unsafe{Mmap::map(&fp)?};
let wad = wad::Wad::new(&mm).unwrap(); let wad = wad::Wad::new(&mm)?;
println!("{:#?}", wad); println!("{:#?}", wad);

View File

@ -1,4 +1,4 @@
use crate::durandal::{bin::*, text::*}; use crate::durandal::{bin::*, err::*, text::*};
use std::fmt; use std::fmt;
impl Terminal impl Terminal

View File

@ -1,6 +1,6 @@
//! Marathon Wad format handling. //! Marathon Wad format handling.
use crate::durandal::{bin::*, 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 Chunk <'a> = &'a[u8];
@ -47,7 +47,7 @@ impl Wad<'_>
pub fn new(b: &[u8]) -> ResultS<Wad> pub fn new(b: &[u8]) -> ResultS<Wad>
{ {
let b = &b[try_mac_header(b)..]; let b = &b[try_mac_header(b)..];
if b.len() < 128 {return Err("not enough data for Wad header")} if b.len() < 128 {return err_msg("not enough data for Wad header")}
let wadver = b.c_u16b( 0)?; let wadver = b.c_u16b( 0)?;
let dataver = b.c_u16b( 2)?; let dataver = b.c_u16b( 2)?;
@ -65,7 +65,7 @@ impl Wad<'_>
2 => Ver::Over, 2 => Ver::Over,
1 => Ver::Dir, 1 => Ver::Dir,
0 => Ver::Base, 0 => Ver::Base,
_ => return Err("invalid Wad version"), _ => return err_msg("invalid Wad version"),
}; };
let is_old = match wadver {Ver::Base => true, _ => false}; let is_old = match wadver {Ver::Base => true, _ => false};
@ -80,7 +80,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("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];