1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std;
use std::io::{Read};
use super::{Result, RawInstruction, Header};
const MAGIC_NUMBER : u32 = 0x07230203;
pub struct Reader<R: ?Sized + Read> {
need_swap: bool,
is_eof: bool,
read_header: bool,
reader: R
}
impl<R: Read> Reader<R> {
pub fn new(mut reader: R) -> Result<Reader<R>> {
let mut word : u32 = 0;
unsafe {
let buf : &mut [u8;4] = std::mem::transmute(&mut word);
try!(reader.read(buf));
}
let need_swap = if word == MAGIC_NUMBER {
false
} else if word.swap_bytes() == MAGIC_NUMBER {
true
} else {
return Err(super::ParseError::InvalidMagicNumber(word));
};
Ok(Reader {
need_swap: need_swap,
is_eof: false,
read_header: false,
reader: reader
})
}
}
impl<R: ?Sized + Read> Reader<R> {
fn read_word(&mut self) -> Result<u32> {
if self.is_eof { return Ok(0); }
let mut word : u32 = 0;
unsafe {
let buf : &mut [u8;4] = std::mem::transmute(&mut word);
let n = try!(self.reader.read(buf));
if n != 4 {
self.is_eof = true;
return Ok(0);
}
}
if self.need_swap {
Ok(word.swap_bytes())
} else {
Ok(word)
}
}
pub fn read_header(&mut self) -> Result<Header> {
assert!(!self.read_header, "Already read header");
let version = try!(self.read_word());
let major = (version >> 16) as u8;
let minor = ((version >> 8) & 0xFF) as u8;
let generator_id = try!(self.read_word());
let id_bound = try!(self.read_word());
try!(self.read_word());
self.read_header = true;
Ok(Header {
version: (major, minor),
generator_id: generator_id,
id_bound: id_bound
})
}
pub fn skip_header(&mut self) -> Result<()> {
if !self.read_header {
self.read_header().map(|_| ())
} else {
Ok(())
}
}
pub fn read_instruction(&mut self) -> Result<Option<RawInstruction>> {
assert!(self.read_header, "Header needs to be read");
let op = try!(self.read_word());
if self.is_eof { return Ok(None); }
let code = (op & 0xFFFF) as u16;
let count = op >> 16;
let mut params = Vec::with_capacity(count as usize);
for _ in 1..count {
let p = try!(self.read_word());
params.push(p);
}
Ok(Some(RawInstruction {
opcode: code,
params: params
}))
}
}