add DEFLATE decoder
parent
745f32f3bd
commit
bd13092188
|
@ -1,13 +1,14 @@
|
||||||
//! DEFLATE loader.
|
//! DEFLATE loader.
|
||||||
|
|
||||||
use crate::durandal::err::*;
|
use crate::durandal::{bit::*, err::*};
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
/// Loads a ZLIB file header.
|
/// Loads a ZLIB file header.
|
||||||
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const CM: u8 = 0b00001111;
|
const CM: u8 = 0b0000_1111;
|
||||||
const CINFO: u8 = 0b11110000;
|
const CINFO: u8 = 0b1111_0000;
|
||||||
const FDICT: u8 = 0b00100000;
|
const FDICT: u8 = 0b0010_0000;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
2, BE in b =>
|
2, BE in b =>
|
||||||
|
@ -33,10 +34,11 @@ pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
||||||
/// Loads a GZIP file header.
|
/// Loads a GZIP file header.
|
||||||
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const FHCRC: u8 = 1 << 1;
|
const FHCRC: u8 = 1 << 1;
|
||||||
const FEXTRA: u8 = 1 << 2;
|
const FEXTRA: u8 = 1 << 2;
|
||||||
const FNAME: u8 = 1 << 3;
|
const FNAME: u8 = 1 << 3;
|
||||||
const FCOMMENT: u8 = 1 << 4;
|
const FCOMMENT: u8 = 1 << 4;
|
||||||
|
const FRESERVED: u8 = 0xE0;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
10, LE in b =>
|
10, LE in b =>
|
||||||
|
@ -51,6 +53,10 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
||||||
|
|
||||||
let mut p = 10;
|
let mut p = 10;
|
||||||
|
|
||||||
|
if fl & FRESERVED != 0 {
|
||||||
|
bail!("reserved flags set");
|
||||||
|
}
|
||||||
|
|
||||||
if fl & FEXTRA != 0 {
|
if fl & FEXTRA != 0 {
|
||||||
read_data!(p + 2, LE in b => xlen = u16[p] usize;);
|
read_data!(p + 2, LE in b => xlen = u16[p] usize;);
|
||||||
check_data!(p + 2 + xlen, b);
|
check_data!(p + 2 + xlen, b);
|
||||||
|
@ -59,11 +65,11 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FNAME != 0 {
|
if fl & FNAME != 0 {
|
||||||
p = skip_zero_terminated_item(&b[p..])?;
|
p += skip_zero_terminated_item(&b[p..])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FCOMMENT != 0 {
|
if fl & FCOMMENT != 0 {
|
||||||
p = skip_zero_terminated_item(&b[p..])?;
|
p += skip_zero_terminated_item(&b[p..])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FHCRC != 0 {
|
if fl & FHCRC != 0 {
|
||||||
|
@ -78,10 +84,315 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
||||||
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
|
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
if let Some(i) = b.iter().position(|&n| n == 0) {
|
if let Some(i) = b.iter().position(|&n| n == 0) {
|
||||||
Ok(i)
|
Ok(i + 1)
|
||||||
} else {
|
} else {
|
||||||
bail!("no end of zero terminated item");
|
bail!("no end of zero terminated item");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decompresses a DEFLATE compressed bitstream.
|
||||||
|
pub fn load_deflate(b: &[u8]) -> ResultS<(usize, Vec<u8>)>
|
||||||
|
{
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let p = stream_deflate(&mut v, b, 0)?;
|
||||||
|
|
||||||
|
Ok((p / 8, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream_deflate(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
|
||||||
|
{
|
||||||
|
let bfinal = read_bits_l(b, p, 1)?;
|
||||||
|
let btype = read_bits_l(b, p + 1, 2)?;
|
||||||
|
|
||||||
|
let p = p + 3;
|
||||||
|
|
||||||
|
let p = match btype {
|
||||||
|
0b10 => stream_dynamic(v, b, p)?,
|
||||||
|
0b01 => stream_s_table(v, b, p)?,
|
||||||
|
0b00 => stream_literal(v, b, p)?,
|
||||||
|
_ => bail!("bad btype"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if bfinal == 0 {
|
||||||
|
stream_deflate(v, b, p)
|
||||||
|
} else {
|
||||||
|
Ok(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream_dynamic(v: &mut Vec<u8>, b: &[u8], mut p: usize) -> ResultS<usize>
|
||||||
|
{
|
||||||
|
const CODE_ORDERING: [usize; NUM_CODES] = [
|
||||||
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||||
|
];
|
||||||
|
|
||||||
|
const NUM_CODES: usize = 19;
|
||||||
|
|
||||||
|
const MAX_LIT_CODES: usize = 286;
|
||||||
|
const MAX_DST_CODES: usize = 30;
|
||||||
|
|
||||||
|
// read header (number of literal alphabet codes, number of distance
|
||||||
|
// alphabet codes, and number of lengths for decoding the alphabet)
|
||||||
|
let hlit = read_bits_l(b, p, 5)?; p += 5;
|
||||||
|
let hdist = read_bits_l(b, p, 5)?; p += 5;
|
||||||
|
let hclen = read_bits_l(b, p, 4)?; p += 4;
|
||||||
|
|
||||||
|
let hlit = 257 + hlit as usize;
|
||||||
|
let hdist = 1 + hdist as usize;
|
||||||
|
let hclen = 4 + hclen as usize;
|
||||||
|
|
||||||
|
let alphabet_total = hlit + hdist;
|
||||||
|
|
||||||
|
// first, get the huffman coding for the alphabet (which is also compressed)
|
||||||
|
let mut code_lengths = [0; NUM_CODES];
|
||||||
|
|
||||||
|
for i in 0..hclen {
|
||||||
|
let len = read_bits_l(b, p, 3)? as u16;
|
||||||
|
p += 3;
|
||||||
|
|
||||||
|
code_lengths[CODE_ORDERING[i]] = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
let code_lengths = HuffmanTable::new(&code_lengths)?;
|
||||||
|
let mut alphabet = [0; MAX_LIT_CODES + MAX_DST_CODES];
|
||||||
|
|
||||||
|
// then, we decode the alphabet (doing both types at the same time, because
|
||||||
|
// they're encoded the same anyways)
|
||||||
|
let mut i = 0;
|
||||||
|
while i < alphabet_total {
|
||||||
|
let (bits, sym) = code_lengths.decode(b, p)?;
|
||||||
|
p += bits;
|
||||||
|
|
||||||
|
match sym {
|
||||||
|
0..=15 => {
|
||||||
|
// raw code
|
||||||
|
alphabet[i] = sym;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
16 => {
|
||||||
|
// copy previous code 3-6 times
|
||||||
|
if i == 0 {bail!("cannot copy on first alphabet code");}
|
||||||
|
|
||||||
|
let len = usize::from(read_bits_l(b, p, 2)? as u8 + 3);
|
||||||
|
let lst = alphabet[i - 1];
|
||||||
|
p += 2;
|
||||||
|
|
||||||
|
for _ in 0..len {
|
||||||
|
alphabet[i] = lst;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
17 => {
|
||||||
|
// repeat '0' 3-10 times
|
||||||
|
let len = usize::from(read_bits_l(b, p, 3)? as u8 + 3);
|
||||||
|
p += 3;
|
||||||
|
|
||||||
|
for _ in 0..len {
|
||||||
|
alphabet[i] = 0;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
18 => {
|
||||||
|
// repeat '0' 11-138 times
|
||||||
|
let len = usize::from(read_bits_l(b, p, 7)? as u8 + 11);
|
||||||
|
p += 7;
|
||||||
|
|
||||||
|
for _ in 0..len {
|
||||||
|
alphabet[i] = 0;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
bail!("bad symbol in alphabet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > alphabet_total {
|
||||||
|
bail!("too many codes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if alphabet[256] == 0 {
|
||||||
|
bail!("no way to end block");
|
||||||
|
}
|
||||||
|
|
||||||
|
let len_sta = 0;
|
||||||
|
let len_end = hlit;
|
||||||
|
let dst_sta = len_end;
|
||||||
|
let dst_end = dst_sta + hdist;
|
||||||
|
|
||||||
|
let table_len = HuffmanTable::new(&alphabet[len_sta..len_end])?;
|
||||||
|
let table_dst = HuffmanTable::new(&alphabet[dst_sta..dst_end])?;
|
||||||
|
|
||||||
|
output_tables(v, b, p, table_len, table_dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream_s_table(_v: &mut Vec<u8>, _b: &[u8], _p: usize) -> ResultS<usize>
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream_literal(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
|
||||||
|
{
|
||||||
|
// copy data directly from byte boundary
|
||||||
|
let mut p = p / 8 + 1;
|
||||||
|
|
||||||
|
read_data! {
|
||||||
|
p + 4, LE in b =>
|
||||||
|
len = u16[p] usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 4;
|
||||||
|
v.extend_from_slice(ok!(b.get(p..p + len), "not enough data")?);
|
||||||
|
|
||||||
|
Ok((p + len) * 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_tables(v: &mut Vec<u8>,
|
||||||
|
b: &[u8],
|
||||||
|
mut p: usize,
|
||||||
|
table_len: HuffmanTable,
|
||||||
|
table_dst: HuffmanTable)
|
||||||
|
-> ResultS<usize>
|
||||||
|
{
|
||||||
|
const LEN_BASE: [usize; 29] = [
|
||||||
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
|
||||||
|
67, 83, 99, 115, 131, 163, 195, 227, 258
|
||||||
|
];
|
||||||
|
|
||||||
|
const LEN_EXTRA_BITS: [u8; 29] = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
|
||||||
|
5, 5, 5, 5, 0
|
||||||
|
];
|
||||||
|
|
||||||
|
const DST_BASE: [usize; 30] = [
|
||||||
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
|
||||||
|
769, 1025, 1537, 2049, 3073, 4097, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001
|
||||||
|
];
|
||||||
|
|
||||||
|
const DST_EXTRA_BITS: [u8; 30] = [
|
||||||
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
|
||||||
|
11, 11, 12, 12, 13, 13
|
||||||
|
];
|
||||||
|
|
||||||
|
let (bits, sym) = table_len.decode(b, p)?;
|
||||||
|
p += bits;
|
||||||
|
|
||||||
|
match sym.cmp(&256) {
|
||||||
|
Ordering::Less => {
|
||||||
|
v.push(sym as u8);
|
||||||
|
output_tables(v, b, p, table_len, table_dst)
|
||||||
|
}
|
||||||
|
Ordering::Equal => {
|
||||||
|
Ok(p)
|
||||||
|
}
|
||||||
|
Ordering::Greater => {
|
||||||
|
let sym = sym - 257;
|
||||||
|
|
||||||
|
if sym > 29 {
|
||||||
|
Err(err_msg("invalid fixed code"))
|
||||||
|
} else {
|
||||||
|
let sym = usize::from(sym);
|
||||||
|
|
||||||
|
let bits = LEN_EXTRA_BITS[sym];
|
||||||
|
let leng = LEN_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
||||||
|
p += usize::from(bits);
|
||||||
|
|
||||||
|
let (bits, sym) = table_dst.decode(b, p)?;
|
||||||
|
p += bits;
|
||||||
|
|
||||||
|
let sym = usize::from(sym);
|
||||||
|
|
||||||
|
let bits = DST_EXTRA_BITS[sym];
|
||||||
|
let dist = DST_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
||||||
|
p += usize::from(bits);
|
||||||
|
|
||||||
|
if dist > v.len() {
|
||||||
|
bail!("bad distance");
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..leng {
|
||||||
|
v.push(v[v.len() - dist]);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_tables(v, b, p, table_len, table_dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HuffmanTable
|
||||||
|
{
|
||||||
|
fn new(table: &[u16]) -> ResultS<Self>
|
||||||
|
{
|
||||||
|
let mut syms = vec![0; table.len()];
|
||||||
|
let mut nums = [0; 16];
|
||||||
|
|
||||||
|
// count the number of symbols for each bit length
|
||||||
|
for &length in table {
|
||||||
|
nums[usize::from(length)] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if usize::from(nums[0]) == table.len() {
|
||||||
|
bail!("bad table lengths");
|
||||||
|
}
|
||||||
|
|
||||||
|
// make offsets into the symbol table for each bit count
|
||||||
|
let mut ofs = [0; 16];
|
||||||
|
|
||||||
|
for i in 1..=14 {
|
||||||
|
ofs[i + 1] = ofs[i] + usize::from(nums[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the actual bit pattern table
|
||||||
|
for (n, &length) in table.iter().enumerate() {
|
||||||
|
// length 0 means this code isn't used, so only try to make bit
|
||||||
|
// patterns for codes that actually exist
|
||||||
|
if length != 0 {
|
||||||
|
// make sure to make each offset unique
|
||||||
|
let offset = &mut ofs[usize::from(length)];
|
||||||
|
syms[*offset] = n as u16;
|
||||||
|
*offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self{nums, syms})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode(&self, b: &[u8], mut p: usize) -> ResultS<(usize, u16)>
|
||||||
|
{
|
||||||
|
let mut code = 0_u16;
|
||||||
|
let mut first = 0_u16;
|
||||||
|
let mut index = 0_u16;
|
||||||
|
|
||||||
|
for i in 1..=15 {
|
||||||
|
// add bit from file
|
||||||
|
code |= read_bits_l(b, p, 1)? as u16;
|
||||||
|
p += 1;
|
||||||
|
|
||||||
|
// check our symbol table for this one (quick tree check)
|
||||||
|
let count = u16::from(self.nums[i]);
|
||||||
|
|
||||||
|
if i32::from(code) - i32::from(count) < i32::from(first) {
|
||||||
|
return Ok((i, self.syms[usize::from(index + code - first)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue on, trying to find the correct sequence
|
||||||
|
index += count;
|
||||||
|
first += count;
|
||||||
|
|
||||||
|
first <<= 1;
|
||||||
|
code <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(err_msg("code not found in symbol tree"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HuffmanTable
|
||||||
|
{
|
||||||
|
nums: [u8; 16],
|
||||||
|
syms: Vec<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
Alice was beginning to get very tired of sitting by her sister on the bank, and
|
||||||
|
of having nothing to do: once or twice she had peeped into the book her sister
|
||||||
|
was reading, but it had no pictures or conversations in it, 'and what is the
|
||||||
|
use of a book,' thought Alice 'without pictures or conversations?'
|
||||||
|
|
||||||
|
So she was considering in her own mind (as well as she could, for the hot day
|
||||||
|
made her feel very sleepy and stupid), whether the pleasure of making a
|
||||||
|
daisy-chain would be worth the trouble of getting up and picking the daisies,
|
||||||
|
when suddenly a White Rabbit with pink eyes ran close by her.
|
||||||
|
|
||||||
|
There was nothing so VERY remarkable in that; nor did Alice think it so VERY
|
||||||
|
much out of the way to hear the Rabbit say to itself, 'Oh dear! Oh dear! I
|
||||||
|
shall be late!' (when she thought it over afterwards, it occurred to her that
|
||||||
|
she ought to have wondered at this, but at the time it all seemed quite
|
||||||
|
natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS
|
||||||
|
WAISTCOAT-POCKET, and looked at it, and then hurried on, Alice started to her
|
||||||
|
feet, for it flashed across her mind that she had never before seen a rabbit
|
||||||
|
with either a waistcoat-pocket, or a watch to take out of it, and burning with
|
||||||
|
curiosity, she ran across the field after it, and fortunately was just in time
|
||||||
|
to see it pop down a large rabbit-hole under the hedge.
|
||||||
|
|
||||||
|
In another moment down went Alice after it, never once considering how in the
|
||||||
|
world she was to get out again.
|
||||||
|
|
||||||
|
The rabbit-hole went straight on like a tunnel for some way, and then dipped
|
||||||
|
suddenly down, so suddenly that Alice had not a moment to think about stopping
|
||||||
|
herself before she found herself falling down a very deep well.
|
||||||
|
|
||||||
|
Either the well was very deep, or she fell very slowly, for she had plenty of
|
||||||
|
time as she went down to look about her and to wonder what was going to happen
|
||||||
|
next. First, she tried to look down and make out what she was coming to, but it
|
||||||
|
was too dark to see anything; then she looked at the sides of the well, and
|
||||||
|
noticed that they were filled with cupboards and book-shelves; here and there
|
||||||
|
she saw maps and pictures hung upon pegs. She took down a jar from one of the
|
||||||
|
shelves as she passed; it was labelled 'ORANGE MARMALADE', but to her great
|
||||||
|
disappointment it was empty: she did not like to drop the jar for fear of
|
||||||
|
killing somebody, so managed to put it into one of the cupboards as she fell
|
||||||
|
past it.
|
||||||
|
|
||||||
|
'Well!' thought Alice to herself, 'after such a fall as this, I shall think
|
||||||
|
nothing of tumbling down stairs! How brave they'll all think me at home! Why, I
|
||||||
|
wouldn't say anything about it, even if I fell off the top of the house!'
|
||||||
|
(Which was very likely true.)
|
||||||
|
|
||||||
|
Down, down, down. Would the fall NEVER come to an end! 'I wonder how many miles
|
||||||
|
I've fallen by this time?' she said aloud. 'I must be getting somewhere near
|
||||||
|
the centre of the earth. Let me see: that would be four thousand miles down, I
|
||||||
|
think--' (for, you see, Alice had learnt several things of this sort in her
|
||||||
|
lessons in the schoolroom, and though this was not a VERY good opportunity for
|
||||||
|
showing off her knowledge, as there was no one to listen to her, still it was
|
||||||
|
good practice to say it over) '--yes, that's about the right distance--but then
|
||||||
|
I wonder what Latitude or Longitude I've got to?' (Alice had no idea what
|
||||||
|
Latitude was, or Longitude either, but thought they were nice grand words to
|
||||||
|
say.)
|
||||||
|
|
||||||
|
Presently she began again. 'I wonder if I shall fall right THROUGH the earth!
|
||||||
|
How funny it'll seem to come out among the people that walk with their heads
|
||||||
|
downward! The Antipathies, I think--' (she was rather glad there WAS no one
|
||||||
|
listening, this time, as it didn't sound at all the right word) '--but I shall
|
||||||
|
have to ask them what the name of the country is, you know. Please, Ma'am, is
|
||||||
|
this New Zealand or Australia?' (and she tried to curtsey as she spoke--fancy
|
||||||
|
CURTSEYING as you're falling through the air! Do you think you could manage
|
||||||
|
it?) 'And what an ignorant little girl she'll think me for asking! No, it'll
|
||||||
|
never do to ask: perhaps I shall see it written up somewhere.'
|
||||||
|
|
||||||
|
Down, down, down. There was nothing else to do, so Alice soon began talking
|
||||||
|
again. 'Dinah'll miss me very much to-night, I should think!' (Dinah was the
|
||||||
|
cat.) 'I hope they'll remember her saucer of milk at tea-time. Dinah my dear! I
|
||||||
|
wish you were down here with me! There are no mice in the air, I'm afraid, but
|
||||||
|
you might catch a bat, and that's very like a mouse, you know. But do cats eat
|
||||||
|
bats, I wonder?' And here Alice began to get rather sleepy, and went on saying
|
||||||
|
to herself, in a dreamy sort of way, 'Do cats eat bats? Do cats eat bats?' and
|
||||||
|
sometimes, 'Do bats eat cats?' for, you see, as she couldn't answer either
|
||||||
|
question, it didn't much matter which way she put it. She felt that she was
|
||||||
|
dozing off, and had just begun to dream that she was walking hand in hand with
|
||||||
|
Dinah, and saying to her very earnestly, 'Now, Dinah, tell me the truth: did
|
||||||
|
you ever eat a bat?' when suddenly, thump! thump! down she came upon a heap of
|
||||||
|
sticks and dry leaves, and the fall was over.
|
||||||
|
|
||||||
|
Alice was not a bit hurt, and she jumped up on to her feet in a moment: she
|
||||||
|
looked up, but it was all dark overhead; before her was another long passage,
|
||||||
|
and the White Rabbit was still in sight, hurrying down it. There was not a
|
||||||
|
moment to be lost: away went Alice like the wind, and was just in time to hear
|
||||||
|
it say, as it turned a corner, 'Oh my ears and whiskers, how late it's
|
||||||
|
getting!' She was close behind it when she turned the corner, but the Rabbit
|
||||||
|
was no longer to be seen: she found herself in a long, low hall, which was lit
|
||||||
|
up by a row of lamps hanging from the roof.
|
||||||
|
|
||||||
|
There were doors all round the hall, but they were all locked; and when Alice
|
||||||
|
had been all the way down one side and up the other, trying every door, she
|
||||||
|
walked sadly down the middle, wondering how she was ever to get out again.
|
||||||
|
|
||||||
|
Suddenly she came upon a little three-legged table, all made of solid glass;
|
||||||
|
there was nothing on it except a tiny golden key, and Alice's first thought was
|
||||||
|
that it might belong to one of the doors of the hall; but, alas! either the
|
||||||
|
locks were too large, or the key was too small, but at any rate it would not
|
||||||
|
open any of them. However, on the second time round, she came upon a low
|
||||||
|
curtain she had not noticed before, and behind it was a little door about
|
||||||
|
fifteen inches high: she tried the little golden key in the lock, and to her
|
||||||
|
great delight it fitted!
|
||||||
|
|
||||||
|
Alice opened the door and found that it led into a small passage, not much
|
||||||
|
larger than a rat-hole: she knelt down and looked along the passage into the
|
||||||
|
loveliest garden you ever saw. How she longed to get out of that dark hall, and
|
||||||
|
wander about among those beds of bright flowers and those cool fountains, but
|
||||||
|
she could not even get her head through the doorway; 'and even if my head would
|
||||||
|
go through,' thought poor Alice, 'it would be of very little use without my
|
||||||
|
shoulders. Oh, how I wish I could shut up like a telescope! I think I could, if
|
||||||
|
I only knew how to begin.' For, you see, so many out-of-the-way things had
|
||||||
|
happened lately, that Alice had begun to think that very few things indeed were
|
||||||
|
really impossible.
|
||||||
|
|
||||||
|
There seemed to be no use in waiting by the little door, so she went back to
|
||||||
|
the table, half hoping she might find another key on it, or at any rate a book
|
||||||
|
of rules for shutting people up like telescopes: this time she found a little
|
||||||
|
bottle on it, ('which certainly was not here before,' said Alice,) and round
|
||||||
|
the neck of the bottle was a paper label, with the words 'DRINK ME' beautifully
|
||||||
|
printed on it in large letters.
|
||||||
|
|
||||||
|
It was all very well to say 'Drink me,' but the wise little Alice was not going
|
||||||
|
to do THAT in a hurry. 'No, I'll look first,' she said, 'and see whether it's
|
||||||
|
marked "poison" or not'; for she had read several nice little histories about
|
||||||
|
children who had got burnt, and eaten up by wild beasts and other unpleasant
|
||||||
|
things, all because they WOULD not remember the simple rules their friends had
|
||||||
|
taught them: such as, that a red-hot poker will burn you if you hold it too
|
||||||
|
long; and that if you cut your finger VERY deeply with a knife, it usually
|
||||||
|
bleeds; and she had never forgotten that, if you drink much from a bottle
|
||||||
|
marked 'poison,' it is almost certain to disagree with you, sooner or later.
|
||||||
|
|
||||||
|
However, this bottle was NOT marked 'poison,' so Alice ventured to taste it,
|
||||||
|
and finding it very nice, (it had, in fact, a sort of mixed flavour of
|
||||||
|
cherry-tart, custard, pine-apple, roast turkey, toffee, and hot buttered
|
||||||
|
toast,) she very soon finished it off.
|
||||||
|
|
||||||
|
* * * * * * *
|
||||||
|
|
||||||
|
* * * * * *
|
||||||
|
|
||||||
|
* * * * * * *
|
||||||
|
|
||||||
|
'What a curious feeling!' said Alice; 'I must be shutting up like a telescope.'
|
||||||
|
|
||||||
|
And so it was indeed: she was now only ten inches high, and her face brightened
|
||||||
|
up at the thought that she was now the right size for going through the little
|
||||||
|
door into that lovely garden. First, however, she waited for a few minutes to
|
||||||
|
see if she was going to shrink any further: she felt a little nervous about
|
||||||
|
this; 'for it might end, you know,' said Alice to herself, 'in my going out
|
||||||
|
altogether, like a candle. I wonder what I should be like then?' And she tried
|
||||||
|
to fancy what the flame of a candle is like after the candle is blown out, for
|
||||||
|
she could not remember ever having seen such a thing.
|
||||||
|
|
||||||
|
After a while, finding that nothing more happened, she decided on going into
|
||||||
|
the garden at once; but, alas for poor Alice! when she got to the door, she
|
||||||
|
found she had forgotten the little golden key, and when she went back to the
|
||||||
|
table for it, she found she could not possibly reach it: she could see it quite
|
||||||
|
plainly through the glass, and she tried her best to climb up one of the legs
|
||||||
|
of the table, but it was too slippery; and when she had tired herself out with
|
||||||
|
trying, the poor little thing sat down and cried.
|
||||||
|
|
||||||
|
'Come, there's no use in crying like that!' said Alice to herself, rather
|
||||||
|
sharply; 'I advise you to leave off this minute!' She generally gave herself
|
||||||
|
very good advice, (though she very seldom followed it), and sometimes she
|
||||||
|
scolded herself so severely as to bring tears into her eyes; and once she
|
||||||
|
remembered trying to box her own ears for having cheated herself in a game of
|
||||||
|
croquet she was playing against herself, for this curious child was very fond
|
||||||
|
of pretending to be two people. 'But it's no use now,' thought poor Alice, 'to
|
||||||
|
pretend to be two people! Why, there's hardly enough of me left to make ONE
|
||||||
|
respectable person!'
|
||||||
|
|
||||||
|
Soon her eye fell on a little glass box that was lying under the table: she
|
||||||
|
opened it, and found in it a very small cake, on which the words 'EAT ME' were
|
||||||
|
beautifully marked in currants. 'Well, I'll eat it,' said Alice, 'and if it
|
||||||
|
makes me grow larger, I can reach the key; and if it makes me grow smaller, I
|
||||||
|
can creep under the door; so either way I'll get into the garden, and I don't
|
||||||
|
care which happens!'
|
||||||
|
|
||||||
|
She ate a little bit, and said anxiously to herself, 'Which way? Which way?',
|
||||||
|
holding her hand on the top of her head to feel which way it was growing, and
|
||||||
|
she was quite surprised to find that she remained the same size: to be sure,
|
||||||
|
this generally happens when one eats cake, but Alice had got so much into the
|
||||||
|
way of expecting nothing but out-of-the-way things to happen, that it seemed
|
||||||
|
quite dull and stupid for life to go on in the common way.
|
||||||
|
|
||||||
|
So she set to work, and very soon finished off the cake.
|
||||||
|
|
||||||
|
* * * * * * *
|
||||||
|
|
||||||
|
* * * * * *
|
||||||
|
|
||||||
|
* * * * * * *
|
Binary file not shown.
Binary file not shown.
|
@ -1,13 +1,33 @@
|
||||||
use maraiah::marathon::defl::{self, load_gzip_header};
|
use maraiah::marathon::defl;
|
||||||
|
|
||||||
include!("data/rand.rs");
|
include!("data/rand.rs");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn defl_alice()
|
||||||
|
{
|
||||||
|
const IN_1: &[u8] = include_bytes!("data/alice1.in");
|
||||||
|
const IN_2: &[u8] = include_bytes!("data/alice2.in");
|
||||||
|
const OUT: &[u8] = include_bytes!("data/alice.out");
|
||||||
|
|
||||||
|
let p = defl::load_gzip_header(IN_1).unwrap();
|
||||||
|
assert_eq!(p, 0x14);
|
||||||
|
|
||||||
|
let b = &IN_1[p..];
|
||||||
|
assert_eq!(defl::load_deflate(b).unwrap().1, OUT.to_vec());
|
||||||
|
|
||||||
|
let p = defl::load_gzip_header(IN_2).unwrap();
|
||||||
|
assert_eq!(p, 0x14);
|
||||||
|
|
||||||
|
let b = &IN_2[p..];
|
||||||
|
assert_eq!(defl::load_deflate(b).unwrap().1, OUT.to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defl_must_succeed()
|
fn defl_must_succeed()
|
||||||
{
|
{
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipok1.bin")).is_ok());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzipok1.bin")).is_ok());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipok2.bin")).is_ok());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzipok2.bin")).is_ok());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipok3.bin")).is_ok());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzipok3.bin")).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -17,13 +37,13 @@ fn defl_must_not_succeed()
|
||||||
assert!(defl::load_gzip_header(inp).is_err());
|
assert!(defl::load_gzip_header(inp).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad1.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad1.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad2.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad2.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad3.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad3.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad4.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad4.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad5.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad5.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad6.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad6.bin")).is_err());
|
||||||
assert!(load_gzip_header(include_bytes!("data/gzipbad7.bin")).is_err());
|
assert!(defl::load_gzip_header(include_bytes!("data/gzbad7.bin")).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
Loading…
Reference in New Issue