From bd13092188d1f1e61d7776fdac77b8b561e2b1a3 Mon Sep 17 00:00:00 2001 From: Marrub Date: Tue, 12 Mar 2019 03:39:09 -0400 Subject: [PATCH] add DEFLATE decoder --- source/marathon/defl.rs | 333 +++++++++++++++++++++++- tests/data/alice.out | 190 ++++++++++++++ tests/data/alice1.in | Bin 0 -> 4816 bytes tests/data/alice2.in | Bin 0 -> 5118 bytes tests/data/{gzipbad1.bin => gzbad1.bin} | Bin tests/data/{gzipbad2.bin => gzbad2.bin} | Bin tests/data/{gzipbad3.bin => gzbad3.bin} | Bin tests/data/{gzipbad4.bin => gzbad4.bin} | Bin tests/data/{gzipbad5.bin => gzbad5.bin} | Bin tests/data/{gzipbad6.bin => gzbad6.bin} | Bin tests/data/{gzipbad7.bin => gzbad7.bin} | Bin tests/defl.rs | 42 ++- 12 files changed, 543 insertions(+), 22 deletions(-) create mode 100644 tests/data/alice.out create mode 100644 tests/data/alice1.in create mode 100644 tests/data/alice2.in rename tests/data/{gzipbad1.bin => gzbad1.bin} (100%) rename tests/data/{gzipbad2.bin => gzbad2.bin} (100%) rename tests/data/{gzipbad3.bin => gzbad3.bin} (100%) rename tests/data/{gzipbad4.bin => gzbad4.bin} (100%) rename tests/data/{gzipbad5.bin => gzbad5.bin} (100%) rename tests/data/{gzipbad6.bin => gzbad6.bin} (100%) rename tests/data/{gzipbad7.bin => gzbad7.bin} (100%) diff --git a/source/marathon/defl.rs b/source/marathon/defl.rs index d2c3f68..ebdcf24 100644 --- a/source/marathon/defl.rs +++ b/source/marathon/defl.rs @@ -1,13 +1,14 @@ //! DEFLATE loader. -use crate::durandal::err::*; +use crate::durandal::{bit::*, err::*}; +use std::cmp::Ordering; /// Loads a ZLIB file header. pub fn load_zlib_header(b: &[u8]) -> ResultS { - const CM: u8 = 0b00001111; - const CINFO: u8 = 0b11110000; - const FDICT: u8 = 0b00100000; + const CM: u8 = 0b0000_1111; + const CINFO: u8 = 0b1111_0000; + const FDICT: u8 = 0b0010_0000; read_data! { 2, BE in b => @@ -33,10 +34,11 @@ pub fn load_zlib_header(b: &[u8]) -> ResultS /// Loads a GZIP file header. pub fn load_gzip_header(b: &[u8]) -> ResultS { - const FHCRC: u8 = 1 << 1; - const FEXTRA: u8 = 1 << 2; - const FNAME: u8 = 1 << 3; - const FCOMMENT: u8 = 1 << 4; + const FHCRC: u8 = 1 << 1; + const FEXTRA: u8 = 1 << 2; + const FNAME: u8 = 1 << 3; + const FCOMMENT: u8 = 1 << 4; + const FRESERVED: u8 = 0xE0; read_data! { 10, LE in b => @@ -51,6 +53,10 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS let mut p = 10; + if fl & FRESERVED != 0 { + bail!("reserved flags set"); + } + if fl & FEXTRA != 0 { read_data!(p + 2, LE in b => xlen = u16[p] usize;); check_data!(p + 2 + xlen, b); @@ -59,11 +65,11 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS } if fl & FNAME != 0 { - p = skip_zero_terminated_item(&b[p..])?; + p += skip_zero_terminated_item(&b[p..])?; } if fl & FCOMMENT != 0 { - p = skip_zero_terminated_item(&b[p..])?; + p += skip_zero_terminated_item(&b[p..])?; } if fl & FHCRC != 0 { @@ -78,10 +84,315 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS fn skip_zero_terminated_item(b: &[u8]) -> ResultS { if let Some(i) = b.iter().position(|&n| n == 0) { - Ok(i) + Ok(i + 1) } else { bail!("no end of zero terminated item"); } } +/// Decompresses a DEFLATE compressed bitstream. +pub fn load_deflate(b: &[u8]) -> ResultS<(usize, Vec)> +{ + let mut v = Vec::new(); + let p = stream_deflate(&mut v, b, 0)?; + + Ok((p / 8, v)) +} + +fn stream_deflate(v: &mut Vec, b: &[u8], p: usize) -> ResultS +{ + 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, b: &[u8], mut p: usize) -> ResultS +{ + 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, _b: &[u8], _p: usize) -> ResultS +{ + unimplemented!() +} + +fn stream_literal(v: &mut Vec, b: &[u8], p: usize) -> ResultS +{ + // 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, + b: &[u8], + mut p: usize, + table_len: HuffmanTable, + table_dst: HuffmanTable) + -> ResultS +{ + 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 + { + 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, +} + // EOF diff --git a/tests/data/alice.out b/tests/data/alice.out new file mode 100644 index 0000000..40e14ca --- /dev/null +++ b/tests/data/alice.out @@ -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. + + * * * * * * * + + * * * * * * + + * * * * * * * diff --git a/tests/data/alice1.in b/tests/data/alice1.in new file mode 100644 index 0000000000000000000000000000000000000000..6a7d4f8d8c8a3a604d0bf4ee3cb152f24217f50d GIT binary patch literal 4816 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 literal 0 HcmV?d00001 diff --git a/tests/data/alice2.in b/tests/data/alice2.in new file mode 100644 index 0000000000000000000000000000000000000000..098c3771571aed8286f89be48dceed76611fdba4 GIT binary patch literal 5118 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 literal 0 HcmV?d00001 diff --git a/tests/data/gzipbad1.bin b/tests/data/gzbad1.bin similarity index 100% rename from tests/data/gzipbad1.bin rename to tests/data/gzbad1.bin diff --git a/tests/data/gzipbad2.bin b/tests/data/gzbad2.bin similarity index 100% rename from tests/data/gzipbad2.bin rename to tests/data/gzbad2.bin diff --git a/tests/data/gzipbad3.bin b/tests/data/gzbad3.bin similarity index 100% rename from tests/data/gzipbad3.bin rename to tests/data/gzbad3.bin diff --git a/tests/data/gzipbad4.bin b/tests/data/gzbad4.bin similarity index 100% rename from tests/data/gzipbad4.bin rename to tests/data/gzbad4.bin diff --git a/tests/data/gzipbad5.bin b/tests/data/gzbad5.bin similarity index 100% rename from tests/data/gzipbad5.bin rename to tests/data/gzbad5.bin diff --git a/tests/data/gzipbad6.bin b/tests/data/gzbad6.bin similarity index 100% rename from tests/data/gzipbad6.bin rename to tests/data/gzbad6.bin diff --git a/tests/data/gzipbad7.bin b/tests/data/gzbad7.bin similarity index 100% rename from tests/data/gzipbad7.bin rename to tests/data/gzbad7.bin diff --git a/tests/defl.rs b/tests/defl.rs index 58a503b..f73f402 100644 --- a/tests/defl.rs +++ b/tests/defl.rs @@ -1,13 +1,33 @@ -use maraiah::marathon::defl::{self, load_gzip_header}; +use maraiah::marathon::defl; 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] fn defl_must_succeed() { - assert!(load_gzip_header(include_bytes!("data/gzipok1.bin")).is_ok()); - assert!(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/gzipok1.bin")).is_ok()); + assert!(defl::load_gzip_header(include_bytes!("data/gzipok2.bin")).is_ok()); + assert!(defl::load_gzip_header(include_bytes!("data/gzipok3.bin")).is_ok()); } #[test] @@ -17,13 +37,13 @@ fn defl_must_not_succeed() assert!(defl::load_gzip_header(inp).is_err()); } - assert!(load_gzip_header(include_bytes!("data/gzipbad1.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad2.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad3.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad4.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad5.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad6.bin")).is_err()); - assert!(load_gzip_header(include_bytes!("data/gzipbad7.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad1.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad2.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad3.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad4.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad5.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad6.bin")).is_err()); + assert!(defl::load_gzip_header(include_bytes!("data/gzbad7.bin")).is_err()); } // EOF