rspirv/binary/
decoder.rs

1use crate::spirv;
2
3use super::DecodeError as Error;
4use std::convert::TryInto;
5use std::result;
6use std::str;
7
8pub type Result<T> = result::Result<T, Error>;
9
10const WORD_NUM_BYTES: usize = 4;
11
12/// The SPIR-V binary decoder.
13///
14/// Takes in a vector of bytes, and serves requests for raw SPIR-V words
15/// or values of a specific SPIR-V enum type. Successful decoding will
16/// surely consume the number of words decoded, while unsuccessful decoding
17/// may consume any number of bytes.
18///
19/// TODO: The decoder should not consume words if an error occurs.
20///
21/// Different from the [`Parser`](struct.Parser.html),
22/// this decoder is low-level; it has no knowledge of the SPIR-V grammar.
23/// Given a vector of bytes, it solely responds to word decoding requests
24/// via method calls: both raw words requests and decoding the raw words
25/// into a value of a specific SPIR-V enum type.
26///
27/// It also provides a limit mechanism. Users can set a limit, and then
28/// requesting words. If that limit is reached before the end of the
29/// stream, [`State::LimitReached`](enum.ParseState.html) will be
30/// returned.
31///
32/// # Errors
33///
34/// For its methods, there can be the following errors:
35///
36/// * `DecodeError::LimitReached(offset)` if the most recent limit has reached.
37/// * `DecodeError::StreamExpected(offset)` if more bytes are needed to decode
38///    the next word.
39/// * `DecodeError::<spirv-enum>Unknown(offset, value)` if failed to decode the
40///    next word as the given `<spirv-enum>`.
41///
42/// All errors contain the byte offset of the word failed decoding.
43///
44/// # Examples
45///
46/// ```
47/// use rspirv::binary::{Decoder, DecodeError};
48/// use spirv::SourceLanguage;
49///
50/// let v = vec![0x12, 0x34, 0x56, 0x78,
51///              0x90, 0xab, 0xcd, 0xef,
52///              0x02, 0x00, 0x00, 0x00];
53/// let mut d = Decoder::new(&v);
54///
55/// assert_eq!(Ok(0x78563412), d.word());
56/// assert_eq!(Ok(0xefcdab90), d.word());
57/// assert_eq!(Ok(SourceLanguage::GLSL), d.source_language());
58///
59/// assert_eq!(Err(DecodeError::StreamExpected(12)), d.word());
60/// ```
61pub struct Decoder<'a> {
62    /// Raw bytes to decode
63    bytes: &'a [u8],
64    /// Offset for next byte to decode
65    offset: usize,
66    /// Remaining limit of number of words before error
67    limit: Option<usize>,
68}
69
70impl<'a> Decoder<'a> {
71    /// Creates a new `Decoder` instance.
72    pub fn new(bytes: &'a [u8]) -> Decoder<'a> {
73        Decoder {
74            bytes,
75            offset: 0,
76            limit: None,
77        }
78    }
79
80    /// Returns the offset of the byte to decode next.
81    pub fn offset(&self) -> usize {
82        self.offset
83    }
84
85    /// Decodes and returns the next raw SPIR-V word.
86    pub fn word(&mut self) -> Result<spirv::Word> {
87        if self.has_limit() {
88            if self.limit_reached() {
89                return Err(Error::LimitReached(self.offset));
90            } else {
91                *self.limit.as_mut().unwrap() -= 1
92            }
93        }
94
95        if self.offset >= self.bytes.len() || self.offset + WORD_NUM_BYTES > self.bytes.len() {
96            Err(Error::StreamExpected(self.offset))
97        } else {
98            self.offset += WORD_NUM_BYTES;
99            Ok(spirv::Word::from_le_bytes(
100                self.bytes[self.offset - 4..self.offset].try_into().unwrap(),
101            ))
102        }
103    }
104
105    /// Decodes and returns the next `n` raw SPIR-V words.
106    pub fn words(&mut self, n: usize) -> Result<Vec<spirv::Word>> {
107        let mut words = Vec::new();
108        for _ in 0..n {
109            words.push(self.word()?);
110        }
111        Ok(words)
112    }
113}
114
115impl<'a> Decoder<'a> {
116    /// Sets the limit to `num_words` words.
117    ///
118    /// The decoder will return [`State::LimitReached`](enum.ParseState.html)
119    /// after `num_words` words have been requested, if having not consumed
120    /// the whole stream.
121    pub fn set_limit(&mut self, num_words: usize) {
122        self.limit = Some(num_words)
123    }
124
125    /// Clear the previously set limit (if any).
126    pub fn clear_limit(&mut self) {
127        self.limit = None
128    }
129
130    /// Returns true if a limit has been set on this decoder.
131    pub fn has_limit(&self) -> bool {
132        self.limit.is_some()
133    }
134
135    /// Returns true if the previously set limit has been reached.
136    ///
137    /// This will always return false if no limit has been ever set.
138    pub fn limit_reached(&self) -> bool {
139        if let Some(left) = self.limit {
140            left == 0
141        } else {
142            false
143        }
144    }
145}
146
147impl<'a> Decoder<'a> {
148    /// Decodes and returns the next SPIR-V word as an id.
149    pub fn id(&mut self) -> Result<spirv::Word> {
150        self.word()
151    }
152
153    /// Decodes and returns a literal string.
154    ///
155    /// This method will consume as many words as necessary until finding a
156    /// null character (`\0`), or reaching the limit or end of the stream
157    /// and erroring out.
158    pub fn string(&mut self) -> Result<String> {
159        // If we have a limit, then don't search further than we need to.
160        let slice = match self.limit {
161            Some(limit) => &self.bytes[self.offset..(self.offset + limit * WORD_NUM_BYTES)],
162            None => &self.bytes[self.offset..],
163        };
164        // Find the null terminator.
165        let first_null_byte = slice.iter().position(|&c| c == 0).ok_or(match self.limit {
166            Some(_) => Error::LimitReached(self.offset + slice.len()),
167            None => Error::StreamExpected(self.offset),
168        })?;
169        // Validate the string is utf8.
170        let result = str::from_utf8(&slice[..first_null_byte])
171            .map_err(|e| Error::DecodeStringFailed(self.offset, format!("{}", e)))?;
172        // Round up consumed words to include null byte(s).
173        let consumed_words = (first_null_byte / WORD_NUM_BYTES) + 1;
174        self.offset += consumed_words * WORD_NUM_BYTES;
175        if let Some(ref mut limit) = self.limit {
176            // This is guaranteed to be enough due to the slice limit above.
177            *limit -= consumed_words;
178        }
179        Ok(result.to_string())
180    }
181
182    /// Decodes and returns the next SPIR-V word as a 32-bit
183    /// literal bit pattern.
184    pub fn bit32(&mut self) -> Result<u32> {
185        self.word()
186    }
187
188    /// Decodes and returns the next two SPIR-V words as a 64-bit
189    /// literal bit pattern.
190    pub fn bit64(&mut self) -> Result<u64> {
191        let low = u64::from(self.word()?);
192        let high = u64::from(self.word()?);
193        Ok((high << 32) | low)
194    }
195
196    /// Decodes and returns the next SPIR-V word as a 32-bit
197    /// extended-instruction-set number.
198    pub fn ext_inst_integer(&mut self) -> Result<u32> {
199        self.word()
200    }
201}
202
203include!("autogen_decode_operand.rs");
204
205#[cfg(test)]
206mod tests {
207    use crate::spirv;
208
209    use super::Decoder;
210    use crate::binary::DecodeError as Error;
211
212    #[test]
213    fn test_decoding_word_from_one_bytes() {
214        let b = vec![1];
215        let mut d = Decoder::new(&b);
216        assert_eq!(Err(Error::StreamExpected(0)), d.word());
217    }
218
219    #[test]
220    fn test_decoding_word_from_two_bytes() {
221        let b = vec![1, 2];
222        let mut d = Decoder::new(&b);
223        assert_eq!(Err(Error::StreamExpected(0)), d.word());
224    }
225
226    #[test]
227    fn test_decoding_word_from_three_bytes() {
228        let b = vec![1, 2, 3];
229        let mut d = Decoder::new(&b);
230        assert_eq!(Err(Error::StreamExpected(0)), d.word());
231    }
232
233    #[test]
234    fn test_decoding_word_from_four_bytes() {
235        let b = vec![0x12, 0x34, 0x56, 0x78];
236        let mut d = Decoder::new(&b);
237        assert_eq!(Ok(0x78563412), d.word());
238    }
239
240    #[test]
241    #[rustfmt::skip]
242    fn test_decoding_words() {
243        let b = vec![0x12, 0x34, 0x56, 0x78,
244                     0x90, 0xab, 0xcd, 0xef,
245                     0x01, 0x23, 0x45, 0x67,
246                     0x89, 0xfe, 0xdc, 0xba];
247        let mut d = Decoder::new(&b);
248        assert_eq!(Ok(vec![0x78563412, 0xefcdab90]), d.words(2));
249        assert_eq!(Ok(vec![0x67452301]), d.words(1));
250        assert_eq!(Ok(vec![0xbadcfe89]), d.words(1));
251    }
252
253    #[test]
254    fn test_decoding_string() {
255        {
256            let b = vec![0x00, 0x00, 0x00, 0x00];
257            let mut d = Decoder::new(&b);
258            assert_eq!(Ok(String::new()), d.string());
259        }
260        {
261            let b = b"ok".to_vec();
262            let mut d = Decoder::new(&b);
263            assert_eq!(Err(Error::StreamExpected(0)), d.string());
264        }
265        {
266            let b = b"ok\0\0".to_vec();
267            let mut d = Decoder::new(&b);
268            assert_eq!(Ok("ok".to_string()), d.string());
269        }
270        {
271            let b = b"ok\0\0rust\0\0\0\0rocks\0\0\0".to_vec();
272            let mut d = Decoder::new(&b);
273            assert_eq!(Ok("ok".to_string()), d.string());
274            assert_eq!(Ok("rust".to_string()), d.string());
275            assert_eq!(Ok("rocks".to_string()), d.string());
276        }
277        {
278            let b = b"I..don't know..\0".to_vec();
279            let mut d = Decoder::new(&b);
280            assert_eq!(Ok("I..don't know..".to_string()), d.string());
281        }
282    }
283
284    #[test]
285    fn test_decoding_source_language() {
286        let b = vec![0x02, 0x00, 0x00, 0x00];
287        let mut d = Decoder::new(&b);
288        assert_eq!(Ok(spirv::SourceLanguage::GLSL), d.source_language());
289    }
290
291    #[test]
292    fn test_decoding_unknown_execution_model() {
293        let b = vec![0xef, 0xbe, 0xad, 0xde];
294        let mut d = Decoder::new(&b);
295        assert_eq!(
296            Err(Error::ExecutionModelUnknown(0, 0xdeadbeef)),
297            d.execution_model()
298        );
299    }
300
301    #[test]
302    #[rustfmt::skip]
303    fn test_offset() {
304        let b = vec![0x12, 0x34, 0x56, 0x78,
305                     0x90, 0xab, 0xcd, 0xef,
306                     0x01, 0x23, 0x45, 0x67,
307                     0x89, 0xfe, 0xdc, 0xba,
308                     0x01, 0x00, 0x00, 0x00,
309                     0xff, 0xff, 0xff, 0xff];
310        let mut d = Decoder::new(&b);
311
312        assert_eq!(0, d.offset());
313        assert!(d.words(1).is_ok());
314        assert_eq!(4, d.offset());
315        assert!(d.words(2).is_ok());
316        assert_eq!(12, d.offset());
317        assert!(d.words(1).is_ok());
318        assert_eq!(16, d.offset());
319
320        assert!(d.source_language().is_ok());
321        assert_eq!(20, d.offset());
322
323        assert!(d.execution_model().is_err());
324        assert_eq!(24, d.offset());
325    }
326
327    #[test]
328    fn test_decoding_after_errors() {
329        let b = vec![0x12, 0x34, 0x56, 0x78];
330        let mut d = Decoder::new(&b);
331        assert_eq!(Ok(0x78563412), d.word());
332        assert_eq!(Err(Error::StreamExpected(4)), d.word());
333        assert_eq!(Err(Error::StreamExpected(4)), d.word());
334        assert_eq!(Err(Error::StreamExpected(4)), d.word());
335    }
336
337    #[test]
338    fn test_limit() {
339        let v = vec![0xff; 12];
340        let mut d = Decoder::new(&v);
341
342        assert!(!d.has_limit());
343        assert!(!d.limit_reached());
344
345        d.set_limit(4);
346        assert!(d.has_limit());
347        assert!(!d.limit_reached());
348
349        d.clear_limit();
350        assert!(!d.has_limit());
351        assert!(!d.limit_reached());
352
353        d.set_limit(2);
354        assert!(d.has_limit());
355        assert!(!d.limit_reached());
356        assert_eq!(Ok(0xffffffff), d.word());
357        assert!(d.has_limit());
358        assert!(!d.limit_reached());
359        assert_eq!(Ok(0xffffffff), d.word());
360        assert!(d.has_limit());
361        assert!(d.limit_reached());
362        assert_eq!(Err(Error::LimitReached(8)), d.word());
363        assert!(d.has_limit());
364        assert!(d.limit_reached());
365        assert_eq!(Err(Error::LimitReached(8)), d.word());
366        assert!(d.has_limit());
367        assert!(d.limit_reached());
368
369        d.clear_limit();
370        assert_eq!(Ok(0xffffffff), d.word());
371        assert!(!d.has_limit());
372        assert!(!d.limit_reached());
373
374        d.set_limit(0);
375        assert_eq!(Err(Error::LimitReached(12)), d.word());
376        assert!(d.has_limit());
377        assert!(d.limit_reached());
378
379        d.clear_limit();
380        assert_eq!(Err(Error::StreamExpected(12)), d.word());
381    }
382
383    #[test]
384    fn test_decode_bit32() {
385        let b = [0x12, 0x34, 0x56, 0x78];
386        let mut d = Decoder::new(&b);
387        assert_eq!(Ok(0x78563412), d.bit32());
388
389        let b = [0x14, 0xAE, 0x29, 0x42];
390        let mut d = Decoder::new(&b);
391        assert_eq!(Ok(42.42f32.to_bits()), d.bit32());
392
393        let b = [0xA4, 0x70, 0x45, 0xC1];
394        let mut d = Decoder::new(&b);
395        assert_eq!(Ok((-12.34f32).to_bits()), d.bit32());
396    }
397
398    #[test]
399    fn test_decode_bit64() {
400        let b = [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef];
401        let mut d = Decoder::new(&b);
402        assert_eq!(Ok(0xefcdab9078563412), d.bit64());
403
404        let b = [0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0x35, 0x45, 0x40];
405        let mut d = Decoder::new(&b);
406        assert_eq!(Ok(42.42f64.to_bits()), d.bit64());
407
408        let b = [0xAE, 0x47, 0xE1, 0x7A, 0x14, 0xAE, 0x28, 0xC0];
409        let mut d = Decoder::new(&b);
410        assert_eq!(Ok((-12.34f64).to_bits()), d.bit64());
411    }
412}