move BinUtils out of a trait

png-branch
an 2019-02-10 23:29:06 -05:00
parent ab34bebcd5
commit 5a569acd7d
6 changed files with 188 additions and 204 deletions

View File

@ -5,113 +5,97 @@ use std::{fmt,
num::NonZeroU16,
slice::SliceIndex};
/// Returns a byte array from `b` at `i`.
pub fn c_data<I>(b: &[u8], i: I) -> ResultS<&<I as SliceIndex<[u8]>>::Output>
where I: SliceIndex<[u8]>
{
ok!(b.get(i), "not enough data")
}
pub trait BinUtil
/// Returns a byte from `b` at `i`.
pub fn c_byte(b: &[u8], i: usize) -> ResultS<u8>
{
/// Returns a byte from `self` at `i`.
fn c_byte(&self, i: usize) -> ResultS<u8>;
/// Returns a four-character-code identifier from `self` at `i`.
fn c_iden(&self, i: usize) -> ResultS<Ident>
{
ok!(self.o_iden(i), "not enough data")
}
/// Returns a big-endian `u32` from `self` at `i`.
fn c_u32b(&self, i: usize) -> ResultS<u32>
{
ok!(self.o_u32b(i), "not enough data")
}
/// Returns a big-endian `u16` from `self` at `i`.
fn c_u16b(&self, i: usize) -> ResultS<u16>
{
ok!(self.o_u16b(i), "not enough data")
}
/// Returns a big-endian `i32` from `self` at `i`.
fn c_i32b(&self, i: usize) -> ResultS<i32>
{
ok!(self.o_i32b(i), "not enough data")
}
/// Returns a big-endian `i16` from `self` at `i`.
fn c_i16b(&self, i: usize) -> ResultS<i16>
{
ok!(self.o_i16b(i), "not enough data")
}
/// Returns a four-character-code identifier from `self` at `i`.
fn o_iden(&self, i: usize) -> Option<Ident>;
/// Returns a big-endian `u32` from `self` at `i`.
fn o_u32b(&self, i: usize) -> Option<u32>;
/// Returns a big-endian `u16` from `self` at `i`.
fn o_u16b(&self, i: usize) -> Option<u16>;
/// Returns a big-endian `i32` from `self` at `i`.
fn o_i32b(&self, i: usize) -> Option<i32>
{
match self.o_u32b(i) {
Some(n) => Some(n as i32),
None => None,
}
}
/// Returns a big-endian `i16` from `self` at `i`.
fn o_i16b(&self, i: usize) -> Option<i16>
{
match self.o_u16b(i) {
Some(n) => Some(n as i16),
None => None,
}
match b.get(i) {
Some(&v) => Ok(v),
None => Err(err_msg("not enough data")),
}
}
impl BinUtil for [u8]
/// Returns a four-character-code identifier from `b` at `i`.
pub fn c_iden(b: &[u8], i: usize) -> ResultS<Ident>
{
fn c_byte(&self, i: usize) -> ResultS<u8>
{
match self.get(i) {
Some(&v) => Ok(v),
None => Err(err_msg("not enough data")),
}
}
ok!(o_iden(b, i), "not enough data")
}
fn o_iden(&self, i: usize) -> Option<Ident>
{
if i + 3 < self.len() {
Some([self[i], self[i + 1], self[i + 2], self[i + 3]])
} else {
None
}
}
/// Returns a big-endian `u32` from `b` at `i`.
pub fn c_u32b(b: &[u8], i: usize) -> ResultS<u32>
{
ok!(o_u32b(b, i), "not enough data")
}
fn o_u32b(&self, i: usize) -> Option<u32>
{
if i + 3 < self.len() {
Some(u32::from_be_bytes([self[i],
self[i + 1],
self[i + 2],
self[i + 3]]))
} else {
None
}
}
/// Returns a big-endian `u16` from `b` at `i`.
pub fn c_u16b(b: &[u8], i: usize) -> ResultS<u16>
{
ok!(o_u16b(b, i), "not enough data")
}
fn o_u16b(&self, i: usize) -> Option<u16>
{
if i + 1 < self.len() {
Some(u16::from_be_bytes([self[i], self[i + 1]]))
} else {
None
}
/// Returns a big-endian `i32` from `b` at `i`.
pub fn c_i32b(b: &[u8], i: usize) -> ResultS<i32>
{
ok!(o_i32b(b, i), "not enough data")
}
/// Returns a big-endian `i16` from `b` at `i`.
pub fn c_i16b(b: &[u8], i: usize) -> ResultS<i16>
{
ok!(o_i16b(b, i), "not enough data")
}
/// Returns a four-character-code identifier from `b` at `i`.
pub fn o_iden(b: &[u8], i: usize) -> Option<Ident>
{
if i + 3 < b.len() {
Some([b[i], b[i + 1], b[i + 2], b[i + 3]])
} else {
None
}
}
/// Returns a big-endian `u32` from `b` at `i`.
pub fn o_u32b(b: &[u8], i: usize) -> Option<u32>
{
if i + 3 < b.len() {
Some(u32::from_be_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]]))
} else {
None
}
}
/// Returns a big-endian `u16` from `b` at `i`.
pub fn o_u16b(b: &[u8], i: usize) -> Option<u16>
{
if i + 1 < b.len() {
Some(u16::from_be_bytes([b[i], b[i + 1]]))
} else {
None
}
}
/// Returns a big-endian `i32` from `b` at `i`.
pub fn o_i32b(b: &[u8], i: usize) -> Option<i32>
{
match o_u32b(b, i) {
Some(n) => Some(n as i32),
None => None,
}
}
/// Returns a big-endian `i16` from `b` at `i`.
pub fn o_i16b(b: &[u8], i: usize) -> Option<i16>
{
match o_u16b(b, i) {
Some(n) => Some(n as i16),
None => None,
}
}

View File

@ -11,12 +11,12 @@ pub fn check_apple_single(b: &[u8]) -> Option<usize>
}
// get the resource fork (entity 1)
let num = b.o_u16b(24)? as usize;
let num = o_u16b(b, 24)? as usize;
for i in 0..num {
let p = 26 + 12 * i;
let ent = b.o_u32b(p)?;
let ofs = b.o_u32b(p + 4)? as usize;
let len = b.o_u32b(p + 8)? as usize;
let ent = o_u32b(b, p)?;
let ofs = o_u32b(b, p + 4)? as usize;
let len = o_u32b(b, p + 8)? as usize;
if ent == 1 {
return if ofs + len > b.len() {None} else {Some(ofs)};
@ -50,7 +50,7 @@ pub fn check_macbin(b: &[u8]) -> Option<usize>
}
// if ok, resource fork follows
if crc == b.o_u16b(124)? {
if crc == o_u16b(b, 124)? {
Some(128)
} else {
None

View File

@ -8,8 +8,8 @@ impl Chunked<Point> for Point
fn read(b: &[u8]) -> ResultS<Self>
{
let x = b.c_i16b(0)?;
let y = b.c_i16b(2)?;
let x = c_i16b(b, 0)?;
let y = c_i16b(b, 2)?;
Ok(Point{x, y})
}
}
@ -20,11 +20,11 @@ impl Chunked<Endpoint> for Endpoint
fn read(b: &[u8]) -> ResultS<Self>
{
let flags = b.c_u16b(0)?;
let adj_hi = b.c_i16b(2)?;
let adj_lo = b.c_i16b(4)?;
let flags = c_u16b(b, 0)?;
let adj_hi = c_i16b(b, 2)?;
let adj_lo = c_i16b(b, 4)?;
let pos = Point::read(c_data(b, 6..10)?)?;
let support = b.c_u16b(14)?;
let support = c_u16b(b, 14)?;
let flags = ok!(EndpFlags::from_bits(flags), "bad EndpFlags")?;
Ok(Endpoint{flags, adj_hi, adj_lo, pos, support})
}
@ -36,16 +36,16 @@ impl Chunked<Line> for Line
fn read(b: &[u8]) -> ResultS<Self>
{
let epnt_f = b.c_u16b(0)?;
let epnt_b = b.c_u16b(2)?;
let flags = b.c_u16b(4)?;
let length = b.c_i16b(6)?;
let adj_hi = b.c_i16b(8)?;
let adj_lo = b.c_i16b(10)?;
let side_f = b.c_u16b(12)?;
let side_b = b.c_u16b(14)?;
let poly_f = b.c_u16b(16)?;
let poly_b = b.c_u16b(18)?;
let epnt_f = c_u16b(b, 0)?;
let epnt_b = c_u16b(b, 2)?;
let flags = c_u16b(b, 4)?;
let length = c_i16b(b, 6)?;
let adj_hi = c_i16b(b, 8)?;
let adj_lo = c_i16b(b, 10)?;
let side_f = c_u16b(b, 12)?;
let side_b = c_u16b(b, 14)?;
let poly_f = c_u16b(b, 16)?;
let poly_b = c_u16b(b, 18)?;
let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?;
Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b,
poly_f, poly_b})
@ -57,7 +57,7 @@ impl SideTex
fn read(b: &[u8]) -> ResultS<Self>
{
let offs = Point::read(c_data(b, 0..4)?)?;
let tex_id = b.c_u16b(4)?;
let tex_id = c_u16b(b, 4)?;
let tex_id = ObjID::from_repr(tex_id);
Ok(SideTex{offs, tex_id})
}
@ -69,8 +69,8 @@ impl Chunked<Side> for Side
fn read(b: &[u8]) -> ResultS<Self>
{
let stype = b.c_u16b(0)?;
let flags = b.c_u16b(2)?;
let stype = c_u16b(b, 0)?;
let flags = c_u16b(b, 2)?;
let tex_pri = SideTex::read(c_data(b, 4..10)?)?;
let tex_sec = SideTex::read(c_data(b, 10..16)?)?;
let tex_tra = SideTex::read(c_data(b, 16..22)?)?;
@ -78,12 +78,12 @@ impl Chunked<Side> for Side
let ex_trigh = Point::read(c_data(b, 26..30)?)?;
let ex_bleft = Point::read(c_data(b, 30..34)?)?;
let ex_brigh = Point::read(c_data(b, 34..38)?)?;
let paneltyp = b.c_u16b(38)?;
let paneldat = b.c_i16b(40)?;
let xfer_pri = b.c_u16b(42)?;
let xfer_sec = b.c_u16b(44)?;
let xfer_tra = b.c_u16b(46)?;
let shade = b.c_u32b(48)?;
let paneltyp = c_u16b(b, 38)?;
let paneldat = c_i16b(b, 40)?;
let xfer_pri = c_u16b(b, 42)?;
let xfer_sec = c_u16b(b, 44)?;
let xfer_tra = c_u16b(b, 46)?;
let shade = c_u32b(b, 48)?;
let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?;
let shade = Fx32::from_bits(shade);
Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
@ -96,13 +96,13 @@ impl Chunker<Minf> for Minf
{
fn chunk(b: &[u8]) -> ResultS<Self>
{
let env_code = b.c_u16b(0)?;
let physi_id = b.c_u16b(2)?;
let music_id = b.c_u16b(4)?;
let msn_flag = b.c_u16b(6)?;
let env_flag = b.c_u16b(8)?;
let env_code = c_u16b(b, 0)?;
let physi_id = c_u16b(b, 2)?;
let music_id = c_u16b(b, 4)?;
let msn_flag = c_u16b(b, 6)?;
let env_flag = c_u16b(b, 8)?;
let levelnam = mac_roman_conv(c_data(b, 18..84)?);
let ent_flag = b.c_u32b(84)?;
let ent_flag = c_u32b(b, 84)?;
let msn_flag = ok!(MsnFlags::from_bits(msn_flag), "bad MsnFlags")?;
let env_flag = ok!(EnvFlags::from_bits(env_flag), "bad EnvFlags")?;
let ent_flag = ok!(EntFlags::from_bits(ent_flag), "bad EntFlags")?;

View File

@ -20,22 +20,22 @@ pub fn read_bitmap_area(mut im: Image8,
let (w, h) = (im.w(), im.h());
let pitch_fl = b.c_u16b(p)?;
let top = b.c_u16b(p + 2)? as usize;
let left = b.c_u16b(p + 4)? as usize;
let bottom = b.c_u16b(p + 6)? as usize;
let right = b.c_u16b(p + 8)? as usize;
// version = b.c_u16b(p+10)?;
let pack_typ = b.c_u16b(p + 12)?;
// pack_siz = b.c_u32b(p+14)?;
// horz_dpi = b.c_u32b(p+18)?;
// vert_dpi = b.c_u32b(p+22)?;
// format = b.c_u16b(p+26)?;
let depth = b.c_u16b(p + 28)?;
// comp_n = b.c_u16b(p+30)?;
// comp_d = b.c_u16b(p+32)?;
// planeofs = b.c_u32b(p+34)?;
// clut_id = b.c_u32b(p+38)?;
let pitch_fl = c_u16b(b, p)?;
let top = c_u16b(b, p + 2)? as usize;
let left = c_u16b(b, p + 4)? as usize;
let bottom = c_u16b(b, p + 6)? as usize;
let right = c_u16b(b, p + 8)? as usize;
// version = c_u16b(b, p+10)?;
let pack_typ = c_u16b(b, p + 12)?;
// pack_siz = c_u32b(b, p+14)?;
// horz_dpi = c_u32b(b, p+18)?;
// vert_dpi = c_u32b(b, p+22)?;
// format = c_u16b(b, p+26)?;
let depth = c_u16b(b, p + 28)?;
// comp_n = c_u16b(b, p+30)?;
// comp_d = c_u16b(b, p+32)?;
// planeofs = c_u32b(b, p+34)?;
// clut_id = c_u32b(b, p+38)?;
if pitch_fl & 0x8000 == 0 {
bail!("PICT1 not supported");
@ -59,7 +59,7 @@ pub fn read_bitmap_area(mut im: Image8,
p += 18; // srcRect, dstRect, mode
if clip {
p += b.c_u16b(p)? as usize; // maskRgn
p += c_u16b(b, p)? as usize; // maskRgn
}
let rle = pack_typ == PACK_DEFAULT ||
@ -75,7 +75,7 @@ pub fn read_bitmap_area(mut im: Image8,
// uncompressed 8-bit colormap indices
for _ in 0..h {
for _ in 0..w {
let idx = b.c_byte((p, p += 1).0)? as usize;
let idx = c_byte(b, (p, p += 1).0)? as usize;
im.cr.push(ok!(clut.get(idx), "invalid index")?.clone());
}
}
@ -90,7 +90,7 @@ pub fn read_bitmap_area(mut im: Image8,
p += pp;
for x in 0..w {
let idx = d.c_byte(x)? as usize;
let idx = c_byte(&d, x)? as usize;
im.cr.push(ok!(clut.get(idx), "invalid index")?.clone());
}
}
@ -105,7 +105,7 @@ pub fn read_bitmap_area(mut im: Image8,
// uncompressed R5G5B5
for _ in 0..h {
for _ in 0..w {
im.cr.push(r5g5b5_to_rgb8(b.c_u16b((p, p += 2).0)?));
im.cr.push(r5g5b5_to_rgb8(c_u16b(b, (p, p += 2).0)?));
}
}
@ -118,7 +118,7 @@ pub fn read_bitmap_area(mut im: Image8,
p += pp;
for x in 0..w {
im.cr.push(r5g5b5_to_rgb8(d.c_u16b(x * 2)?));
im.cr.push(r5g5b5_to_rgb8(c_u16b(&d, x * 2)?));
}
}
@ -135,9 +135,9 @@ pub fn read_bitmap_area(mut im: Image8,
if pack_typ != PACK_NOPAD {
p += 1;
}
let r = b.c_byte(p)?;
let g = b.c_byte(p + 1)?;
let b = b.c_byte(p + 2)?;
let r = c_byte(b, p)?;
let g = c_byte(b, p + 1)?;
let b = c_byte(b, p + 2)?;
p += 3;
im.cr.push(Color8::new(r, g, b));
}
@ -153,9 +153,9 @@ pub fn read_bitmap_area(mut im: Image8,
p += pp;
for x in 0..w {
let r = d.c_byte(x + w)?;
let g = d.c_byte(x + w * 1)?;
let b = d.c_byte(x + w * 2)?;
let r = c_byte(&d, x + w)?;
let g = c_byte(&d, x + w * 1)?;
let b = c_byte(&d, x + w * 2)?;
im.cr.push(Color8::new(r, g, b));
}
}
@ -178,17 +178,17 @@ pub fn read_quicktime_c(_im: Image8, _b: &[u8]) -> ResultS<Image8>
/// Load a PICT image.
pub fn load_pict(b: &[u8]) -> ResultS<Image8>
{
// size = b.c_u16b(0)?;
// top = b.c_u16b(2)?;
// left = b.c_u16b(4)?;
let h = b.c_u16b(6)? as usize;
let w = b.c_u16b(8)? as usize;
// size = c_u16b(b, 0)?;
// top = c_u16b(b, 2)?;
// left = c_u16b(b, 4)?;
let h = c_u16b(b, 6)? as usize;
let w = c_u16b(b, 8)? as usize;
let im = Image8::new(w, h);
let mut p = 10; // size of header
while p < b.len() {
let op = b.c_u16b((p, p += 2).0)?;
let op = c_u16b(b, (p, p += 2).0)?;
match op {
0x0098 => {
@ -260,8 +260,8 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0c00 => p += 24, // HeaderOp
0x0001 => p += (b.c_u16b(p )? & !1) as usize, // Clip
0x00a1 => p += (b.c_u16b(p+2)? & !1) as usize + 2, // LongComment
0x0001 => p += (c_u16b(b, p )? & !1) as usize, // Clip
0x00a1 => p += (c_u16b(b, p+2)? & !1) as usize + 2, // LongComment
0x100..=
0x7fff => p += (op >> 8) as usize * 2, // Reserved
_ => {
@ -276,19 +276,19 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
/// Read a colorTable structure.
pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{
// sed = b.c_u32b(0)?;
let dev = b.c_u16b(4)? & 0x8000 != 0;
let num = b.c_u16b(6)? as usize + 1;
// sed = c_u32b(b, 0)?;
let dev = c_u16b(b, 4)? & 0x8000 != 0;
let num = c_u16b(b, 6)? as usize + 1;
let mut p = 8;
let mut clut = vec![Color8::new(0, 0, 0); num];
for i in 0..num {
// with device mapping, we ignore the index entirely
let n = if !dev {b.c_byte(p + 1)? as usize} else {i};
let r = b.c_byte(p + 2)?;
let g = b.c_byte(p + 4)?;
let b = b.c_byte(p + 6)?;
let n = if !dev {c_byte(b, p + 1)? as usize} else {i};
let r = c_byte(b, p + 2)?;
let g = c_byte(b, p + 4)?;
let b = c_byte(b, p + 6)?;
if n >= clut.len() {
bail!("bad clut index");
@ -309,13 +309,13 @@ pub fn read_rle(b: &[u8], pitch: usize, ln: bool) -> ResultS<(Vec<u8>, usize)>
let mut o = Vec::with_capacity(pitch);
let sz = if pitch > 250 {
(b.c_u16b(0)? as usize + 2, p += 2).0
(c_u16b(b, 0)? as usize + 2, p += 2).0
} else {
(b.c_byte(0)? as usize + 1, p += 1).0
(c_byte(b, 0)? as usize + 1, p += 1).0
};
while p < sz {
let szf = b.c_byte((p, p += 1).0)?;
let szf = c_byte(b, (p, p += 1).0)?;
let cmp = szf & 0x80 != 0;
let len = if cmp {!szf + 2} else {szf + 1} as usize;

View File

@ -3,12 +3,12 @@ use std::fmt;
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{
// flags = b.c_u16b( 0)?;
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)?;
// flags = c_u16b(b, 0)?;
let ttype = c_u16b(b, 2)?;
let pdata = c_i16b(b, 4)?;
let start = c_u16b(b, 6)? as usize;
let size = c_u16b(b, 8)? as usize;
let lines = c_u16b(b, 10)?;
let text = c_data(text, start..start + size)?;
let text = mac_roman_conv(text);
let ttype = GroupType::from_repr(ttype)?;
@ -18,9 +18,9 @@ fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
fn read_face(b: &[u8]) -> ResultS<Face>
{
let start = b.c_u16b(0)? as usize;
let face = b.c_u16b(2)?;
let color = b.c_u16b(4)?;
let start = c_u16b(b, 0)? as usize;
let face = c_u16b(b, 2)?;
let color = c_u16b(b, 4)?;
Ok(Face { start, face, color })
}
@ -30,11 +30,11 @@ fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
const SIZE_GROUP: usize = 12;
const SIZE_FACE: usize = 6;
let end = b.c_u16b(0)? as usize;
let encoded = b.c_u16b(2)? & 1 != 0;
let lines = b.c_u16b(4)?;
let group_n = b.c_u16b(6)? as usize;
let face_n = b.c_u16b(8)? as usize;
let end = c_u16b(b, 0)? as usize;
let encoded = c_u16b(b, 2)? & 1 != 0;
let lines = c_u16b(b, 4)?;
let group_n = c_u16b(b, 6)? as usize;
let face_n = c_u16b(b, 8)? as usize;
let mut groups = Vec::with_capacity(group_n);
let mut faces = Vec::with_capacity(face_n);

View File

@ -7,16 +7,16 @@ impl Wad<'_>
{
pub fn new(b: &[u8]) -> ResultS<Wad>
{
let wadver = b.c_u16b(0)?;
let dataver = b.c_u16b(2)?;
let wadver = c_u16b(b, 0)?;
let dataver = c_u16b(b, 2)?;
let origname = c_data(b, 4..68)?;
// crc = b.c_u32b(68)?;
let dirofs = b.c_u32b(72)? as usize;
let numents = b.c_u16b(76)? as usize;
let appsize = b.c_u16b(78)? as usize;
let wcnksize = b.c_u16b(80)? as usize;
let wentsize = b.c_u16b(82)? as usize;
// parent = b.c_u32b(84)?;
// crc = c_u32b(b, 68)?;
let dirofs = c_u32b(b, 72)? as usize;
let numents = c_u16b(b, 76)? as usize;
let appsize = c_u16b(b, 78)? as usize;
let wcnksize = c_u16b(b, 80)? as usize;
let wentsize = c_u16b(b, 82)? as usize;
// parent = c_u32b(b, 84)?;
let wadver = Ver::from_repr(wadver)?;
let origname = mac_roman_conv(origname);
@ -39,9 +39,9 @@ impl Wad<'_>
let mut p = dirofs;
for i in 0..numents {
let offset = b.c_u32b(p)? 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 offset = c_u32b(b, p)? as usize;
let size = c_u32b(b, p + 4)? as usize;
let index = if !is_old {c_u16b(b, p + 8)?} else {i as u16};
if offset + size > b.len() {
bail!("not enough data for entry");
@ -66,10 +66,10 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
let mut p = 0;
while p < b.len() {
let iden = b.c_iden(p)?;
// ofs = b.c_u32b(p+ 4)?;
let size = b.c_u32b(p + 8)? as usize;
// pofs = b.c_u32b(p+12)?;
let iden = c_iden(b, p)?;
// ofs = c_u32b(b, p+ 4)?;
let size = c_u32b(b, p + 8)? as usize;
// pofs = c_u32b(b, p+12)?;
let beg = p + cnksize;
let end = beg + size;
chunks.insert(iden, c_data(b, beg..end)?);