extra sanity checks and tests
parent
6e3fff0080
commit
f3e98c0c05
|
@ -299,6 +299,38 @@ pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Applies a read function a number of times over a slice.
|
||||||
|
///
|
||||||
|
/// Applies `read` over `b`, resulting in a vector of its return values. Each
|
||||||
|
/// iteration will pass a slice of `b` to `read` for it to read from, and then
|
||||||
|
/// increments the slice index by the second return value. When `n` elements
|
||||||
|
/// have been read, the function returns.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// A panic will occur if the `read` function returns a disjoint index or
|
||||||
|
/// otherwise panics (by an out of bounds index to `b` or otherwise.)
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Execution will return the result of `read` if `read` returns an error.
|
||||||
|
pub fn rd_array_num<T, F>(b: &[u8], n: usize, read: F)
|
||||||
|
-> ResultS<(Vec<T>, usize)>
|
||||||
|
where T: Sized,
|
||||||
|
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||||
|
{
|
||||||
|
let mut v = Vec::with_capacity(n);
|
||||||
|
let mut p = 0;
|
||||||
|
|
||||||
|
for _ in 0..n {
|
||||||
|
let (r, s) = read(&b[p..])?;
|
||||||
|
v.push(r);
|
||||||
|
p += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((v, p))
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies a read function over a slice with an offset table.
|
/// Applies a read function over a slice with an offset table.
|
||||||
///
|
///
|
||||||
/// Applies `read` over each offset in `b`, of which there are `num` amount of
|
/// Applies `read` over each offset in `b`, of which there are `num` amount of
|
||||||
|
|
|
@ -207,6 +207,10 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
|
||||||
w = u16[8] usize;
|
w = u16[8] usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if w * h > 16_000_000 {
|
||||||
|
bail!("image is too large");
|
||||||
|
}
|
||||||
|
|
||||||
let im = Image8::new(w, h);
|
let im = Image8::new(w, h);
|
||||||
|
|
||||||
let mut p = 10; // size of header
|
let mut p = 10; // size of header
|
||||||
|
@ -425,7 +429,7 @@ impl ReadRleData for u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand packed pixel data based on bit depth.
|
/// Expand packed pixel data based on bit depth.
|
||||||
pub fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
|
fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(match depth {
|
let mut o = Vec::with_capacity(match depth {
|
||||||
4 => b.len() * 2,
|
4 => b.len() * 2,
|
||||||
|
|
|
@ -23,12 +23,12 @@ fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let cr = ColorShp::Opaque{r, g, b, l};
|
let cr = ColorShp::Opaque{r, g, b, l};
|
||||||
clut[usize::from(i)] = cr;
|
*ok!(clut.get_mut(usize::from(i)), "bad index")? = cr;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads all color tables.
|
/// Reads all color tables.
|
||||||
pub fn color_tables(b: &[u8],
|
fn color_tables(b: &[u8],
|
||||||
tab_ofs: usize,
|
tab_ofs: usize,
|
||||||
tab_num: usize,
|
tab_num: usize,
|
||||||
clr_num: usize)
|
clr_num: usize)
|
||||||
|
@ -36,14 +36,14 @@ pub fn color_tables(b: &[u8],
|
||||||
{
|
{
|
||||||
let end = tab_num * clr_num * 8;
|
let end = tab_num * clr_num * 8;
|
||||||
|
|
||||||
let b = &b[tab_ofs..tab_ofs + end];
|
let b = ok!(b.get(tab_ofs..tab_ofs + end), "bad offset")?;
|
||||||
|
|
||||||
let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
|
let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
for clut in v.iter_mut().take(tab_num) {
|
for clut in v.iter_mut().take(tab_num) {
|
||||||
for _ in 0..clr_num {
|
for _ in 0..clr_num {
|
||||||
read_color(&b[p..p + 8], clut)?;
|
read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?;
|
||||||
p += 8;
|
p += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
|
||||||
bmp.cr.push(0);
|
bmp.cr.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp.cr.extend_from_slice(&b[p..p + end]);
|
bmp.cr.extend_from_slice(ok!(b.get(p..p + end), "not enough data")?);
|
||||||
|
|
||||||
for _ in lst..pitch {
|
for _ in lst..pitch {
|
||||||
bmp.cr.push(0);
|
bmp.cr.push(0);
|
||||||
|
@ -112,7 +112,8 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
|
||||||
bail!("invalid scanline");
|
bail!("invalid scanline");
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp.cr.extend_from_slice(&b[p..p + width * height]);
|
bmp.cr.extend_from_slice(ok!(b.get(p..p + width * height),
|
||||||
|
"not enough data")?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(bmp)
|
Ok(bmp)
|
||||||
|
@ -215,13 +216,15 @@ pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
|
||||||
let c_lo = if lo_ofs == usize_from_u32(u32::max_value()) {
|
let c_lo = if lo_ofs == usize_from_u32(u32::max_value()) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(read_collection(&b[lo_ofs..lo_ofs + lo_len])?)
|
let dat = ok!(b.get(lo_ofs..lo_ofs + lo_len), "bad offset")?;
|
||||||
|
Some(read_collection(dat)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
let c_hi = if hi_ofs == usize_from_u32(u32::max_value()) {
|
let c_hi = if hi_ofs == usize_from_u32(u32::max_value()) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(read_collection(&b[hi_ofs..hi_ofs + hi_len])?)
|
let dat = ok!(b.get(hi_ofs..hi_ofs + hi_len), "bad offset")?;
|
||||||
|
Some(read_collection(dat)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
cl.push((c_lo, c_hi));
|
cl.push((c_lo, c_hi));
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
//! Structures used by Marathon's Map format's terminal definitions.
|
//! Structures used by Marathon's Map format's terminal definitions.
|
||||||
|
|
||||||
use crate::durandal::{err::*, text::*};
|
use crate::durandal::{bin::*, err::*, text::*};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
|
||||||
/// Reads a `Group`.
|
/// Reads an `InterGroup`.
|
||||||
pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
12, BE in b =>
|
12, BE in b =>
|
||||||
flags = u16[0];
|
flags = u16[0];
|
||||||
ttype = u16[2];
|
ttype = u16[2];
|
||||||
pdata = u16[4];
|
pdata = u16[4];
|
||||||
start = u16[6] usize;
|
beg = u16[6] usize;
|
||||||
size = u16[8] usize;
|
len = u16[8] usize;
|
||||||
lines = u16[10];
|
lines = u16[10];
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = ok!(text.get(start..start + size), "not enough data")?;
|
|
||||||
let text = mac_roman_cstr(text)?;
|
|
||||||
let flags = flag_ok!(GroupFlags, flags)?;
|
let flags = flag_ok!(GroupFlags, flags)?;
|
||||||
let ttype = match ttype {
|
let ttype = match ttype {
|
||||||
0 => GroupType::Logon(pdata),
|
0 => GroupType::Logon(pdata),
|
||||||
|
@ -40,11 +38,11 @@ pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
||||||
n => return Err(ReprError::new(n).into()),
|
n => return Err(ReprError::new(n).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Group{flags, ttype, lines, text})
|
Ok((InterGroup{flags, ttype, lines, beg, len}, 12))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `Face`.
|
/// Reads a `Face`.
|
||||||
pub fn read_face(b: &[u8]) -> ResultS<Face>
|
pub fn read_face(b: &[u8]) -> ResultS<(Face, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
6, BE in b =>
|
6, BE in b =>
|
||||||
|
@ -53,15 +51,12 @@ pub fn read_face(b: &[u8]) -> ResultS<Face>
|
||||||
color = u16[4];
|
color = u16[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Face{start, face, color})
|
Ok((Face{start, face, color}, 6))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `term` chunk.
|
/// Reads a `term` chunk.
|
||||||
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
||||||
{
|
{
|
||||||
const SIZE_GROUP: usize = 12;
|
|
||||||
const SIZE_FACE: usize = 6;
|
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
10, BE in b =>
|
10, BE in b =>
|
||||||
end = u16[0] usize;
|
end = u16[0] usize;
|
||||||
|
@ -73,32 +68,34 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
||||||
|
|
||||||
let encoded = encoded != 0;
|
let encoded = encoded != 0;
|
||||||
|
|
||||||
|
let (i_grp, x) = rd_array_num(&b[10..], group_n, read_group)?;
|
||||||
|
let (faces, y) = rd_array_num(&b[10 + x..], face_n, read_face)?;
|
||||||
|
|
||||||
|
let text = ok!(b.get(10 + x + y..end), "not enough data")?;
|
||||||
|
let text = if encoded {fuck_string(text)} else {text.to_vec()};
|
||||||
|
|
||||||
let mut groups = Vec::with_capacity(group_n);
|
let mut groups = Vec::with_capacity(group_n);
|
||||||
let mut faces = Vec::with_capacity(face_n);
|
|
||||||
|
|
||||||
let mut p = 10;
|
for grp in &i_grp {
|
||||||
|
let flags = grp.flags;
|
||||||
|
let ttype = grp.ttype;
|
||||||
|
let lines = grp.lines;
|
||||||
|
let beg = grp.beg;
|
||||||
|
let len = grp.len;
|
||||||
|
let text = ok!(text.get(beg..beg + len), "bad offset")?;
|
||||||
|
let text = mac_roman_cstr(text)?;
|
||||||
|
|
||||||
let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n;
|
groups.push(Group{flags, ttype, lines, text});
|
||||||
let text = ok!(b.get(text_st..end), "bad offset")?;
|
|
||||||
let text = if encoded {
|
|
||||||
fuck_string(text)
|
|
||||||
} else {
|
|
||||||
text.to_vec()
|
|
||||||
};
|
|
||||||
|
|
||||||
for _ in 0..group_n {
|
|
||||||
groups.push(read_group(ok!(b.get(p..), "not enough data")?, &text)?);
|
|
||||||
p += SIZE_GROUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ in 0..face_n {
|
|
||||||
faces.push(read_face(ok!(b.get(p..), "not enough data")?)?);
|
|
||||||
p += SIZE_FACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Terminal{lines, groups, faces}, end))
|
Ok((Terminal{lines, groups, faces}, end))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for GroupType
|
||||||
|
{
|
||||||
|
fn default() -> Self {GroupType::Unfinished}
|
||||||
|
}
|
||||||
|
|
||||||
/// A terminal definition, with collections of groups and faces.
|
/// A terminal definition, with collections of groups and faces.
|
||||||
#[derive(Debug, PartialEq, serde::Serialize)]
|
#[derive(Debug, PartialEq, serde::Serialize)]
|
||||||
pub struct Terminal
|
pub struct Terminal
|
||||||
|
@ -127,8 +124,19 @@ pub struct Group
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interim structure.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterGroup
|
||||||
|
{
|
||||||
|
flags: GroupFlags,
|
||||||
|
ttype: GroupType,
|
||||||
|
lines: u16,
|
||||||
|
beg: usize,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
/// The command of a `Group`.
|
/// The command of a `Group`.
|
||||||
#[derive(Debug, PartialEq, serde::Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize)]
|
||||||
pub enum GroupType
|
pub enum GroupType
|
||||||
{
|
{
|
||||||
Logon(u16),
|
Logon(u16),
|
||||||
|
@ -152,7 +160,7 @@ pub enum GroupType
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// Flags for `Group`.
|
/// Flags for `Group`.
|
||||||
#[derive(serde::Serialize)]
|
#[derive(Default, serde::Serialize)]
|
||||||
pub struct GroupFlags: u16
|
pub struct GroupFlags: u16
|
||||||
{
|
{
|
||||||
const DrawOnRight = 1;
|
const DrawOnRight = 1;
|
||||||
|
|
34
tests/map.rs
34
tests/map.rs
|
@ -1,39 +1,7 @@
|
||||||
use maraiah::{durandal::{bin, fixed::*}, marathon::{map, trm}};
|
use maraiah::{durandal::{bin, fixed::*}, marathon::map};
|
||||||
|
|
||||||
include!("data/rand.rs");
|
include!("data/rand.rs");
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn read_term_must_process()
|
|
||||||
{
|
|
||||||
const INPUT: &[u8] = include_bytes!("data/term.in");
|
|
||||||
|
|
||||||
let inp = bin::rd_array(INPUT, trm::read_term).unwrap();
|
|
||||||
let out = include!("data/term.out");
|
|
||||||
|
|
||||||
// for better debug output, we iterate over each item
|
|
||||||
assert_eq!(inp.len(), out.len());
|
|
||||||
|
|
||||||
for (itrm, otrm) in inp.iter().zip(&out) {
|
|
||||||
assert_eq!(itrm.groups.len(), otrm.groups.len());
|
|
||||||
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
|
|
||||||
assert_eq!(igrp, ogrp);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(itrm.faces.len(), otrm.faces.len());
|
|
||||||
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
|
|
||||||
assert_eq!(ifac, ofac);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn trm_must_not_process()
|
|
||||||
{
|
|
||||||
for inp in &RANDOM {
|
|
||||||
assert!(bin::rd_array(inp, trm::read_term).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_minf_must_process()
|
fn read_minf_must_process()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,24 +1,7 @@
|
||||||
use maraiah::{durandal::image::Color8, marathon::{machdr, pict}};
|
use maraiah::marathon::machdr;
|
||||||
|
|
||||||
include!("data/rand.rs");
|
include!("data/rand.rs");
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_clut_must_process()
|
|
||||||
{
|
|
||||||
const INPUT: &[u8] = include_bytes!("data/clut.in");
|
|
||||||
const OUTPUT: [Color8; 256] = include!("data/clut.out");
|
|
||||||
|
|
||||||
assert_eq!(pict::get_clut(INPUT).unwrap(), (OUTPUT.to_vec(), 2056));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_clut_must_not_process()
|
|
||||||
{
|
|
||||||
for inp in &RANDOM {
|
|
||||||
assert!(pict::get_clut(inp).is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn machdr_must_process()
|
fn machdr_must_process()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
use maraiah::{durandal::bin, marathon::phy};
|
||||||
|
|
||||||
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn phy_must_not_process()
|
||||||
|
{
|
||||||
|
// these functions must not succeed
|
||||||
|
for inp in &RANDOM {
|
||||||
|
assert!(bin::rd_array(inp, phy::read_fxpx).is_err());
|
||||||
|
assert!(bin::rd_array(inp, phy::read_mnpx).is_err());
|
||||||
|
assert!(bin::rd_array(inp, phy::read_prpx).is_err());
|
||||||
|
assert!(bin::rd_array(inp, phy::read_wppx).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
fn phy_wont_panic()
|
||||||
|
{
|
||||||
|
// these functions can succeed but must never panic
|
||||||
|
for inp in &RANDOM {
|
||||||
|
bin::rd_array(inp, phy::read_pxpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
|
@ -0,0 +1,23 @@
|
||||||
|
use maraiah::{durandal::image::Color8, marathon::pict};
|
||||||
|
|
||||||
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_clut_must_process()
|
||||||
|
{
|
||||||
|
const INPUT: &[u8] = include_bytes!("data/clut.in");
|
||||||
|
const OUTPUT: [Color8; 256] = include!("data/clut.out");
|
||||||
|
|
||||||
|
assert_eq!(pict::get_clut(INPUT).unwrap(), (OUTPUT.to_vec(), 2056));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pict_must_not_process()
|
||||||
|
{
|
||||||
|
for inp in &RANDOM {
|
||||||
|
assert!(pict::get_clut(inp).is_err());
|
||||||
|
assert!(pict::load_pict(inp).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
|
@ -0,0 +1,17 @@
|
||||||
|
use maraiah::marathon::shp;
|
||||||
|
|
||||||
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shp_must_not_process()
|
||||||
|
{
|
||||||
|
for inp in &RANDOM {
|
||||||
|
assert!(shp::read_bitmap(inp).is_err());
|
||||||
|
assert!(shp::read_collection(inp).is_err());
|
||||||
|
assert!(shp::read_frame(inp).is_err());
|
||||||
|
assert!(shp::read_sequence(inp).is_err());
|
||||||
|
assert!(shp::read_shapes(inp).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
|
@ -0,0 +1,15 @@
|
||||||
|
use maraiah::marathon::snd;
|
||||||
|
|
||||||
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn snd_must_not_process()
|
||||||
|
{
|
||||||
|
for inp in &RANDOM {
|
||||||
|
assert!(snd::read_sound(inp).is_err());
|
||||||
|
assert!(snd::read_sound_def(inp).is_err());
|
||||||
|
assert!(snd::read_sounds(inp).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
|
@ -0,0 +1,47 @@
|
||||||
|
use maraiah::{durandal::bin, marathon::trm};
|
||||||
|
|
||||||
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read_term_must_process()
|
||||||
|
{
|
||||||
|
const INPUT: &[u8] = include_bytes!("data/term.in");
|
||||||
|
|
||||||
|
let inp = bin::rd_array(INPUT, trm::read_term).unwrap();
|
||||||
|
let out = include!("data/term.out");
|
||||||
|
|
||||||
|
// for better debug output, we iterate over each item
|
||||||
|
assert_eq!(inp.len(), out.len());
|
||||||
|
|
||||||
|
for (itrm, otrm) in inp.iter().zip(&out) {
|
||||||
|
assert_eq!(itrm.groups.len(), otrm.groups.len());
|
||||||
|
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
|
||||||
|
assert_eq!(igrp, ogrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(itrm.faces.len(), otrm.faces.len());
|
||||||
|
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
|
||||||
|
assert_eq!(ifac, ofac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trm_must_not_process()
|
||||||
|
{
|
||||||
|
for inp in &RANDOM {
|
||||||
|
assert!(bin::rd_array(inp, trm::read_group).is_err());
|
||||||
|
assert!(bin::rd_array(inp, trm::read_term).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
fn trm_wont_panic()
|
||||||
|
{
|
||||||
|
for inp in &RANDOM {
|
||||||
|
bin::rd_array(inp, trm::read_face);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
Loading…
Reference in New Issue