spirv_utils/parse/
read.rs

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