1use crate::{
4 core::*,
5 ParseResult, ParseError,
6 op,
7};
8
9#[derive(Clone, Copy)]
13pub struct Stream<'a> {
14 spirv: &'a [u32],
15 version: u32,
16 bound: u32,
17 pos: usize,
18}
19
20impl<'a> Stream<'a> {
21
22 #[inline(always)]
24 pub fn new(spirv: &'a [u32]) -> ParseResult<Self> {
25 if spirv.len() < 5 { return Err(ParseError::EndOfStream) }
26 let magic_number = spirv[0];
27 if magic_number != 0x07230203 {
28 return Err(ParseError::InvalidMagicNumber(magic_number))
29 }
30 Ok(Self {
31 spirv: &spirv[5..],
32 version: spirv[1],
33 bound: spirv[3],
34 pos: 0,
35 })
36 }
37
38 #[inline(always)]
40 pub fn reset(&mut self) {
41 self.pos = 0;
42 }
43
44 #[inline(always)]
46 pub fn version(&self) -> u32 {
47 self.version
48 }
49
50 #[inline(always)]
52 pub fn bound(&self) -> u32 {
53 self.bound
54 }
55}
56
57#[derive(Clone, Copy)]
59pub struct InstructionStream<'a> {
60 op: op::Code,
61 words: &'a [u32],
62 pos: usize,
63}
64
65impl<'a> InstructionStream<'a> {
66
67 #[inline]
71 pub fn code(&self) -> op::Code {
72 self.op
73 }
74
75 #[inline]
77 pub fn is_eos(&self) -> bool {
78 self.pos == self.words.len()
79 }
80
81 #[inline]
83 pub fn reset(&mut self) {
84 self.pos = 1;
85 }
86
87 #[inline]
89 pub fn advance(&mut self, count: u32) -> ParseResult<()> {
90 let end = self.pos + count as usize;
91 if end > self.words.len() { Err(ParseError::EndOfStream) }
92 else {
93 self.pos = end;
94 Ok(())
95 }
96 }
97
98 #[inline]
100 pub fn read(&mut self) -> ParseResult<u32> {
101 let len = self.words.len();
102 let pos = self.pos;
103 if pos == len { Err(ParseError::EndOfStream) }
104 else {
105 self.pos += 1;
106 Ok(self.words[pos])
107 }
108 }
109
110 #[inline]
114 pub fn read_words(&mut self, count: Option<u32>) -> ParseResult<&'a [u32]> {
115 let len = self.words.len();
116 let pos = self.pos;
117 if pos == len { Ok(Default::default()) }
118 else {
119 let end = count
120 .map(|count| pos + count as usize)
121 .unwrap_or(len);
122 if end > len { Err(ParseError::EndOfStream) }
123 else {
124 self.pos = end;
125 Ok(&self.words[pos..end])
126 }
127 }
128 }
129
130 #[inline]
134 pub fn read_string(&mut self) -> ParseResult<CompilerStr<'a>> {
135 let pos = self.pos;
136 if pos == self.words.len() { Err(ParseError::EndOfStream) }
137 else {
138 let str = CompilerStr::new(&self.words[pos..]);
139 let div = str.len() / 4;
140 let mul = 4 * div;
141 self.pos = pos + div + if str.len() - mul != 0 { 1 } else { 0 };
142 Ok(str)
143 }
144 }
145}
146
147impl<'a> Iterator for Stream<'a> {
148
149 type Item = InstructionStream<'a>;
150
151 #[inline]
152 fn next(&mut self) -> Option<Self::Item> {
153 let len = self.spirv.len();
154 let pos = self.pos;
155 if pos == len { None }
156 else {
157 let word = self.spirv[pos];
158 let (count, op_code) = (word >> 16, word & 0xFFFF);
159 let end = pos + count as usize;
160 if end > len { None }
161 else {
162 let instruction = InstructionStream {
163 op: op::Code(op_code as u16),
164 words: &self.spirv[pos..end],
165 pos: 1,
166 };
167 self.pos = end;
168 Some(instruction)
169 }
170 }
171 }
172}