rspirv/binary/
parser.rs

1use crate::dr;
2use crate::grammar;
3use crate::spirv;
4
5use super::{
6    decoder,
7    tracker::{Type, TypeTracker},
8    DecodeError,
9};
10use std::{error, fmt, result, slice};
11
12use crate::grammar::CoreInstructionTable as GInstTable;
13use crate::grammar::OperandKind as GOpKind;
14use crate::grammar::OperandQuantifier as GOpCount;
15
16use crate::utils::version;
17
18type GInstRef = &'static grammar::Instruction<'static>;
19
20const WORD_NUM_BYTES: usize = 4;
21
22/// Parser State.
23///
24/// Most of the error variants will retain the error location for both byte
25/// offset (starting from 0) and instruction number (starting from 1).
26#[derive(Debug)]
27pub enum State {
28    /// Parsing completed
29    Complete,
30    /// Consumer requested to stop parse
31    ConsumerStopRequested,
32    /// Consumer errored out with the given error
33    ConsumerError(Box<dyn error::Error + Send + Sync>),
34    /// Incomplete module header
35    HeaderIncomplete(DecodeError),
36    /// Incorrect module header
37    HeaderIncorrect,
38    /// Unsupported endianness
39    EndiannessUnsupported,
40    /// Zero instruction word count at (byte offset, inst number)
41    WordCountZero(usize, usize),
42    /// Unknown opcode at (byte offset, inst number, opcode)
43    OpcodeUnknown(usize, usize, u16),
44    /// Expected more operands (byte offset, inst number)
45    OperandExpected(usize, usize),
46    /// found redundant operands (byte offset, inst number)
47    OperandExceeded(usize, usize),
48    /// Errored out when decoding operand with the given error
49    OperandError(DecodeError),
50    /// Unsupported type (byte offset, inst number)
51    TypeUnsupported(usize, usize),
52    /// Incorrect SpecConstantOp Integer (byte offset, inst number)
53    SpecConstantOpIntegerIncorrect(usize, usize),
54}
55
56impl From<DecodeError> for State {
57    fn from(err: DecodeError) -> Self {
58        State::OperandError(err)
59    }
60}
61
62impl error::Error for State {}
63
64impl fmt::Display for State {
65    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66        match *self {
67            State::Complete => write!(f, "completed parsing"),
68            State::ConsumerStopRequested => write!(f, "stop parsing requested by consumer"),
69            State::ConsumerError(ref err) => write!(f, "consumer error: {}", err),
70            State::HeaderIncomplete(ref err) => write!(f, "incomplete module header: {}", err),
71            State::HeaderIncorrect => write!(f, "incorrect module header"),
72            State::EndiannessUnsupported => write!(f, "unsupported endianness"),
73            State::WordCountZero(offset, index) => write!(
74                f,
75                "zero word count found for instruction #{} at offset {}",
76                index, offset
77            ),
78            State::OpcodeUnknown(offset, index, opcode) => write!(
79                f,
80                "unknown opcode ({}) for instruction #{} at offset {}",
81                opcode, index, offset
82            ),
83            State::OperandExpected(offset, index) => write!(
84                f,
85                "expected more operands for instruction #{} at offset {}",
86                index, offset
87            ),
88            State::OperandExceeded(offset, index) => write!(
89                f,
90                "found extra operands for instruction #{} at offset {}",
91                index, offset
92            ),
93            State::OperandError(ref err) => write!(f, "operand decoding error: {}", err),
94            State::TypeUnsupported(offset, index) => write!(
95                f,
96                "unsupported type for instruction #{} at offset {}",
97                index, offset
98            ),
99            State::SpecConstantOpIntegerIncorrect(offset, index) => write!(
100                f,
101                "incorrect SpecConstantOp number for instruction #{} at offset {}",
102                index, offset
103            ),
104        }
105    }
106}
107
108pub type Result<T> = result::Result<T, State>;
109
110const HEADER_NUM_WORDS: usize = 5;
111
112/// Orders consumer sent to the parser after each consuming call.
113#[derive(Debug)]
114pub enum Action {
115    /// Continue the parsing
116    Continue,
117    /// Normally stop the parsing
118    Stop,
119    /// Error out with the given error
120    Error(Box<dyn error::Error + Send + Sync>),
121}
122
123impl Action {
124    fn consume(self) -> Result<()> {
125        match self {
126            Action::Continue => Ok(()),
127            Action::Stop => Err(State::ConsumerStopRequested),
128            Action::Error(err) => Err(State::ConsumerError(err)),
129        }
130    }
131}
132
133/// The binary consumer trait.
134///
135/// The parser will call `initialize` before parsing the SPIR-V binary and
136/// `finalize` after successfully parsing the whle binary.
137///
138/// After successfully parsing the module header, `consume_header` will be
139/// called. After successfully parsing an instruction, `consume_instruction`
140/// will be called.
141///
142/// The consumer can use [`Action`](enum.ParseAction.html) to control the
143/// parsing process.
144pub trait Consumer {
145    /// Intialize the consumer.
146    fn initialize(&mut self) -> Action;
147    /// Finalize the consumer.
148    fn finalize(&mut self) -> Action;
149
150    /// Consume the module header.
151    fn consume_header(&mut self, module: dr::ModuleHeader) -> Action;
152    /// Consume the given instruction.
153    fn consume_instruction(&mut self, inst: dr::Instruction) -> Action;
154}
155
156/// Parses the given `binary` and consumes the module using the given
157/// `consumer`.
158pub fn parse_bytes(binary: impl AsRef<[u8]>, consumer: &mut dyn Consumer) -> Result<()> {
159    Parser::new(binary.as_ref(), consumer).parse()
160}
161
162/// Parses the given `binary` and consumes the module using the given
163/// `consumer`.
164pub fn parse_words(binary: impl AsRef<[u32]>, consumer: &mut dyn Consumer) -> Result<()> {
165    let len = binary.as_ref().len() * 4;
166    let buf = unsafe { slice::from_raw_parts(binary.as_ref().as_ptr() as *const u8, len) };
167    Parser::new(buf, consumer).parse()
168}
169
170/// The SPIR-V binary parser.
171///
172/// Takes in a vector of bytes and a consumer, this parser will invoke the
173/// consume methods on the consumer for the module header and each
174/// instruction parsed.
175///
176/// Different from the [`Decoder`](struct.Decoder.html),
177/// this parser is high-level; it has knowlege of the SPIR-V grammar.
178/// It will parse instructions according to SPIR-V grammar.
179///
180/// # Examples
181///
182/// ```
183/// use spirv::{AddressingModel, MemoryModel};
184/// use rspirv::binary::Parser;
185/// use rspirv::dr::{Loader, Operand};
186///
187/// let bin = vec![
188///     // Magic number.           Version number: 1.0.
189///     0x03, 0x02, 0x23, 0x07,    0x00, 0x00, 0x01, 0x00,
190///     // Generator number: 0.    Bound: 0.
191///     0x00, 0x00, 0x00, 0x00,    0x00, 0x00, 0x00, 0x00,
192///     // Reserved word: 0.
193///     0x00, 0x00, 0x00, 0x00,
194///     // OpMemoryModel.          Logical.
195///     0x0e, 0x00, 0x03, 0x00,    0x00, 0x00, 0x00, 0x00,
196///     // GLSL450.
197///     0x01, 0x00, 0x00, 0x00];
198/// let mut loader = Loader::new();  // You can use your own consumer here.
199/// {
200///     let p = Parser::new(&bin, &mut loader);
201///     p.parse().unwrap();
202/// }
203/// let module = loader.module();
204///
205/// assert_eq!((1, 0), module.header.unwrap().version());
206/// let m = module.memory_model.as_ref().unwrap();
207/// assert_eq!(Operand::AddressingModel(AddressingModel::Logical),
208///            m.operands[0]);
209/// assert_eq!(Operand::MemoryModel(MemoryModel::GLSL450),
210///            m.operands[1]);
211/// ```
212pub struct Parser<'c, 'd> {
213    decoder: decoder::Decoder<'d>,
214    consumer: &'c mut dyn Consumer,
215    type_tracker: TypeTracker,
216    /// The index of the current instructions
217    ///
218    /// Starting from 1, 0 means invalid
219    inst_index: usize,
220}
221
222impl<'c, 'd> Parser<'c, 'd> {
223    /// Creates a new parser to parse the given `binary` and send the module
224    /// header and instructions to the given `consumer`.
225    pub fn new(binary: &'d [u8], consumer: &'c mut dyn Consumer) -> Self {
226        Parser {
227            decoder: decoder::Decoder::new(binary),
228            consumer,
229            type_tracker: TypeTracker::new(),
230            inst_index: 0,
231        }
232    }
233
234    /// Does the parsing.
235    pub fn parse(mut self) -> Result<()> {
236        self.consumer.initialize().consume()?;
237        let header = self.parse_header()?;
238        self.consumer.consume_header(header).consume()?;
239
240        loop {
241            let result = self.parse_inst();
242            match result {
243                Ok(inst) => {
244                    self.type_tracker.track(&inst);
245                    self.consumer.consume_instruction(inst).consume()?;
246                }
247                Err(State::Complete) => break,
248                Err(error) => return Err(error),
249            };
250        }
251        self.consumer.finalize().consume()
252    }
253
254    fn split_into_word_count_and_opcode(word: spirv::Word) -> (u16, u16) {
255        ((word >> 16) as u16, (word & 0xffff) as u16)
256    }
257
258    fn parse_header(&mut self) -> Result<dr::ModuleHeader> {
259        match self.decoder.words(HEADER_NUM_WORDS) {
260            Ok(words) => {
261                if words[0] != spirv::MAGIC_NUMBER {
262                    if words[0] == spirv::MAGIC_NUMBER.swap_bytes() {
263                        return Err(State::EndiannessUnsupported);
264                    } else {
265                        return Err(State::HeaderIncorrect);
266                    }
267                }
268
269                let mut header = dr::ModuleHeader::new(words[3]);
270                let (major, minor) = version::create_version_from_word(words[1]);
271                header.set_version(major, minor);
272
273                Ok(header)
274            }
275            Err(err) => Err(State::HeaderIncomplete(err)),
276        }
277    }
278
279    fn parse_inst(&mut self) -> Result<dr::Instruction> {
280        self.inst_index += 1;
281        if let Ok(word) = self.decoder.word() {
282            let (wc, opcode) = Parser::split_into_word_count_and_opcode(word);
283            if wc == 0 {
284                return Err(State::WordCountZero(
285                    self.decoder.offset() - WORD_NUM_BYTES,
286                    self.inst_index,
287                ));
288            }
289            if let Some(grammar) = GInstTable::lookup_opcode(opcode) {
290                self.decoder.set_limit((wc - 1) as usize);
291                let result = self.parse_operands(grammar)?;
292                if !self.decoder.limit_reached() {
293                    return Err(State::OperandExceeded(
294                        self.decoder.offset(),
295                        self.inst_index,
296                    ));
297                }
298                self.decoder.clear_limit();
299                Ok(result)
300            } else {
301                Err(State::OpcodeUnknown(
302                    self.decoder.offset() - WORD_NUM_BYTES,
303                    self.inst_index,
304                    opcode,
305                ))
306            }
307        } else {
308            Err(State::Complete)
309        }
310    }
311
312    fn parse_literal(&mut self, type_id: spirv::Word) -> Result<dr::Operand> {
313        let tracked_type = self.type_tracker.resolve(type_id);
314        match tracked_type {
315            Some(t) => match t {
316                Type::Integer(size, _) => match size {
317                    // "Value is the bit pattern for the constant. Types 32 bits wide or smaller take one word."
318                    8 => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
319                    16 => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
320                    32 => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
321                    64 => Ok(dr::Operand::LiteralBit64(self.decoder.bit64()?)),
322                    _ => Err(State::TypeUnsupported(
323                        self.decoder.offset(),
324                        self.inst_index,
325                    )),
326                },
327                Type::Float(size) => match size {
328                    16 => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
329                    32 => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
330                    64 => Ok(dr::Operand::LiteralBit64(self.decoder.bit64()?)),
331                    _ => Err(State::TypeUnsupported(
332                        self.decoder.offset(),
333                        self.inst_index,
334                    )),
335                },
336            },
337            // Treat as a normal SPIR-V word if we don't know the type.
338            // TODO: find a better way to handle this.
339            None => Ok(dr::Operand::LiteralBit32(self.decoder.bit32()?)),
340        }
341    }
342
343    fn parse_spec_constant_op(&mut self) -> Result<Vec<dr::Operand>> {
344        let mut operands = vec![];
345
346        let number = self.decoder.bit32()?;
347        if let Some(g) = GInstTable::lookup_opcode(number as u16) {
348            // TODO: check whether this opcode is allowed here.
349            operands.push(dr::Operand::LiteralSpecConstantOpInteger(g.opcode));
350
351            // We need all parameters to this SpecConstantOp.
352            for loperand in g.operands {
353                if loperand.kind != GOpKind::IdResultType && loperand.kind != GOpKind::IdResult {
354                    operands.append(&mut self.parse_operand(loperand.kind)?);
355                }
356            }
357            Ok(operands)
358        } else {
359            Err(State::SpecConstantOpIntegerIncorrect(
360                self.decoder.offset(),
361                self.inst_index,
362            ))
363        }
364    }
365
366    fn parse_operands(&mut self, grammar: GInstRef) -> Result<dr::Instruction> {
367        let mut rtype = None;
368        let mut rid = None;
369        let mut coperands = vec![]; // concrete operands
370
371        let mut loperand_index: usize = 0; // logical operand index
372        while loperand_index < grammar.operands.len() {
373            let loperand = &grammar.operands[loperand_index];
374            let has_more_coperands = !self.decoder.limit_reached();
375            if has_more_coperands {
376                match loperand.kind {
377                    GOpKind::IdResultType => rtype = Some(self.decoder.id()?),
378                    GOpKind::IdResult => rid = Some(self.decoder.id()?),
379                    GOpKind::LiteralContextDependentNumber => {
380                        // Only constant defining instructions use this kind.
381                        // If it is not true, that means the grammar is wrong
382                        // or has changed.
383                        assert!(
384                            grammar.opcode == spirv::Op::Constant
385                                || grammar.opcode == spirv::Op::SpecConstant
386                        );
387                        let id = rtype.expect(
388                            "internal error: \
389                            should already decoded result type id before context dependent number",
390                        );
391                        coperands.push(self.parse_literal(id)?)
392                    }
393                    GOpKind::PairLiteralIntegerIdRef => {
394                        assert_eq!(grammar.opcode, spirv::Op::Switch);
395                        let selector = match coperands[0] {
396                            dr::Operand::IdRef(id) => id,
397                            _ => panic!("internal error: OpSwitch selector should be IdRef"),
398                        };
399                        coperands.push(self.parse_literal(selector)?);
400                        coperands.push(dr::Operand::IdRef(self.decoder.id()?));
401                    }
402                    GOpKind::LiteralSpecConstantOpInteger => {
403                        coperands.append(&mut self.parse_spec_constant_op()?)
404                    }
405                    _ => coperands.append(&mut self.parse_operand(loperand.kind)?),
406                }
407                match loperand.quantifier {
408                    GOpCount::One | GOpCount::ZeroOrOne => loperand_index += 1,
409                    GOpCount::ZeroOrMore => continue,
410                }
411            } else {
412                // We still have logical operands to match but no no more words.
413                match loperand.quantifier {
414                    GOpCount::One => {
415                        return Err(State::OperandExpected(
416                            self.decoder.offset(),
417                            self.inst_index,
418                        ))
419                    }
420                    GOpCount::ZeroOrOne | GOpCount::ZeroOrMore => break,
421                }
422            }
423        }
424        Ok(dr::Instruction::new(grammar.opcode, rtype, rid, coperands))
425    }
426}
427
428include!("autogen_parse_operand.rs");
429
430#[cfg(test)]
431mod tests {
432    use assert_matches::assert_matches;
433
434    use crate::dr;
435    use crate::spirv;
436
437    use super::{parse_words, Action, Consumer, Parser, State, WORD_NUM_BYTES};
438    use crate::binary::DecodeError;
439    use std::{error, fmt};
440
441    // TODO: It's unfortunate that we have these numbers directly coded here
442    // and repeat them in the following tests. Should have a better way.
443    #[rustfmt::skip]
444    static ZERO_BOUND_HEADER: &[u8] = &[
445        // Magic number.           Version number: 1.0.
446        0x03, 0x02, 0x23, 0x07,    0x00, 0x00, 0x01, 0x00,
447        // Generator number: 0.    Bound: 0.
448        0x00, 0x00, 0x00, 0x00,    0x00, 0x00, 0x00, 0x00,
449        // Reserved word: 0.
450        0x00, 0x00, 0x00, 0x00];
451
452    struct RetainingConsumer {
453        pub header: Option<dr::ModuleHeader>,
454        pub insts: Vec<dr::Instruction>,
455    }
456    impl RetainingConsumer {
457        fn new() -> RetainingConsumer {
458            RetainingConsumer {
459                header: None,
460                insts: vec![],
461            }
462        }
463    }
464    impl Consumer for RetainingConsumer {
465        fn initialize(&mut self) -> Action {
466            Action::Continue
467        }
468        fn finalize(&mut self) -> Action {
469            Action::Continue
470        }
471
472        fn consume_header(&mut self, header: dr::ModuleHeader) -> Action {
473            self.header = Some(header);
474            Action::Continue
475        }
476        fn consume_instruction(&mut self, inst: dr::Instruction) -> Action {
477            self.insts.push(inst);
478            Action::Continue
479        }
480    }
481
482    // TODO: Should put this function and its duplicate in the decoder in
483    // a utility module.
484    fn w2b(word: spirv::Word) -> Vec<u8> {
485        (0..WORD_NUM_BYTES)
486            .map(|i| ((word >> (8 * i)) & 0xff) as u8)
487            .collect()
488    }
489
490    /// A simple module builder for testing purpose.
491    struct ModuleBuilder {
492        insts: Vec<u8>,
493    }
494    impl ModuleBuilder {
495        fn new() -> ModuleBuilder {
496            ModuleBuilder {
497                insts: ZERO_BOUND_HEADER.to_vec(),
498            }
499        }
500
501        /// Appends an instruction with the given `opcode` and `operands` into
502        /// the module.
503        fn inst(&mut self, opcode: spirv::Op, operands: Vec<u32>) {
504            let count: u32 = operands.len() as u32 + 1;
505            self.insts.append(&mut w2b((count << 16) | (opcode as u32)));
506            for o in operands {
507                self.insts.append(&mut w2b(o));
508            }
509        }
510
511        /// Returns the module being constructed.
512        fn get(&self) -> &[u8] {
513            &self.insts
514        }
515    }
516
517    #[test]
518    fn test_module_builder() {
519        let mut b = ModuleBuilder::new();
520        // OpNop
521        b.inst(spirv::Op::Nop, vec![]);
522        // OpCapability Int16
523        b.inst(spirv::Op::Capability, vec![22]);
524        // OpMemoryModel Logical GLSL450
525        b.inst(spirv::Op::MemoryModel, vec![0, 1]);
526        let mut module = ZERO_BOUND_HEADER.to_vec();
527        module.append(&mut vec![0x00, 0x00, 0x01, 0x00]); // OpNop
528        module.append(&mut vec![0x11, 0x00, 0x02, 0x00]); // OpCapability
529        module.append(&mut vec![0x16, 0x00, 0x00, 0x00]); // Int16
530        module.append(&mut vec![0x0e, 0x00, 0x03, 0x00]); // OpMemoryModel
531        module.append(&mut vec![0x00, 0x00, 0x00, 0x00]); // Logical
532        module.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // GLSL450
533        assert_eq!(module, b.get());
534    }
535
536    #[test]
537    fn test_parsing_empty_binary() {
538        let v = vec![];
539        let mut c = RetainingConsumer::new();
540        let p = Parser::new(&v, &mut c);
541        assert_matches!(
542            p.parse(),
543            Err(State::HeaderIncomplete(DecodeError::StreamExpected(0)))
544        );
545    }
546
547    #[test]
548    fn test_parsing_incomplete_header() {
549        let v = vec![0x03, 0x02, 0x23, 0x07];
550        let mut c = RetainingConsumer::new();
551        let p = Parser::new(&v, &mut c);
552        assert_matches!(
553            p.parse(),
554            Err(State::HeaderIncomplete(DecodeError::StreamExpected(4)))
555        );
556    }
557
558    #[test]
559    fn test_parsing_unsupported_endianness() {
560        let mut module = ZERO_BOUND_HEADER.to_vec();
561        module.as_mut_slice().swap(0, 3);
562        module.as_mut_slice().swap(1, 2);
563        let mut c = RetainingConsumer::new();
564        let p = Parser::new(&module, &mut c);
565        assert_matches!(p.parse(), Err(State::EndiannessUnsupported));
566    }
567
568    #[test]
569    fn test_parsing_wrong_magic_number() {
570        let mut module = ZERO_BOUND_HEADER.to_vec();
571        module[0] = 0x00;
572        let mut c = RetainingConsumer::new();
573        let p = Parser::new(&module, &mut c);
574        assert_matches!(p.parse(), Err(State::HeaderIncorrect));
575    }
576
577    #[test]
578    fn test_parsing_complete_header() {
579        let mut c = RetainingConsumer::new();
580        {
581            let p = Parser::new(ZERO_BOUND_HEADER, &mut c);
582            assert_matches!(p.parse(), Ok(()));
583        }
584        let mut header = dr::ModuleHeader::new(0);
585        header.set_version(1, 0);
586        assert_eq!(Some(header), c.header);
587    }
588
589    #[test]
590    fn test_parsing_one_inst() {
591        let mut c = RetainingConsumer::new();
592        {
593            let mut b = ModuleBuilder::new();
594            // OpMemoryModel Logical GLSL450
595            b.inst(spirv::Op::MemoryModel, vec![0, 1]);
596            let p = Parser::new(b.get(), &mut c);
597            assert_matches!(p.parse(), Ok(()));
598        }
599        assert_eq!(1, c.insts.len());
600        let inst = &c.insts[0];
601        assert_eq!("MemoryModel", inst.class.opname);
602        assert_eq!(None, inst.result_type);
603        assert_eq!(None, inst.result_id);
604        assert_eq!(
605            vec![
606                dr::Operand::AddressingModel(spirv::AddressingModel::Logical),
607                dr::Operand::MemoryModel(spirv::MemoryModel::GLSL450)
608            ],
609            inst.operands
610        );
611    }
612
613    #[test]
614    fn test_parsing_zero_word_count() {
615        let mut v = ZERO_BOUND_HEADER.to_vec();
616        v.append(&mut vec![0x00, 0x00, 0x00, 0x00]); // OpNop with word count 0
617        let mut c = RetainingConsumer::new();
618        let p = Parser::new(&v, &mut c);
619        // The first instruction starts at byte offset 20.
620        assert_matches!(p.parse(), Err(State::WordCountZero(20, 1)));
621    }
622
623    #[test]
624    fn test_parsing_extra_operand() {
625        let mut v = ZERO_BOUND_HEADER.to_vec();
626        v.append(&mut vec![0x00, 0x00, 0x01, 0x00]); // OpNop with word count 1
627        v.append(&mut vec![0x00, 0x00, 0x02, 0x00]); // OpNop with word count 2
628        v.append(&mut vec![0x00, 0x00, 0x00, 0x00]); // A bogus operand
629        let mut c = RetainingConsumer::new();
630        let p = Parser::new(&v, &mut c);
631        // The bogus operand to the second OpNop instruction starts at
632        // byte offset (20 + 4 + 4).
633        assert_matches!(p.parse(), Err(State::OperandExceeded(28, 2)));
634    }
635
636    #[test]
637    fn test_parsing_missing_operand() {
638        let mut v = ZERO_BOUND_HEADER.to_vec();
639        v.append(&mut vec![0x00, 0x00, 0x01, 0x00]); // OpNop with word count 1
640        v.append(&mut vec![0x0e, 0x00, 0x03, 0x00]); // OpMemoryModel
641        v.append(&mut vec![0x00, 0x00, 0x00, 0x00]); // Logical
642        let mut c = RetainingConsumer::new();
643        let p = Parser::new(&v, &mut c);
644        // The missing operand to the OpMemoryModel instruction starts at
645        // byte offset (20 + 4 + 4 + 4).
646        assert_matches!(
647            p.parse(),
648            Err(State::OperandError(DecodeError::StreamExpected(32)))
649        );
650    }
651
652    #[test]
653    fn test_parsing_operand_parameters() {
654        let mut v = ZERO_BOUND_HEADER.to_vec();
655        v.append(&mut vec![0x47, 0x00, 0x04, 0x00]); // OpDecorate
656        v.append(&mut vec![0x05, 0x00, 0x00, 0x00]); // id 5
657        v.append(&mut vec![0x0b, 0x00, 0x00, 0x00]); // BuiltIn
658        v.append(&mut vec![0x06, 0x00, 0x00, 0x00]); // InstanceId
659        let mut c = RetainingConsumer::new();
660        {
661            let p = Parser::new(&v, &mut c);
662            assert_matches!(p.parse(), Ok(()));
663        }
664        assert_eq!(1, c.insts.len());
665        let inst = &c.insts[0];
666        assert_eq!("Decorate", inst.class.opname);
667        assert_eq!(None, inst.result_type);
668        assert_eq!(None, inst.result_id);
669        assert_eq!(
670            vec![
671                dr::Operand::IdRef(5),
672                dr::Operand::Decoration(spirv::Decoration::BuiltIn),
673                dr::Operand::BuiltIn(spirv::BuiltIn::InstanceId)
674            ],
675            inst.operands
676        );
677    }
678
679    #[test]
680    fn test_parsing_missing_operand_parameters() {
681        let mut v = ZERO_BOUND_HEADER.to_vec();
682        v.append(&mut vec![0x47, 0x00, 0x03, 0x00]); // OpDecorate
683        v.append(&mut vec![0x05, 0x00, 0x00, 0x00]); // id 5
684        v.append(&mut vec![0x0b, 0x00, 0x00, 0x00]); // BuiltIn
685        let mut c = RetainingConsumer::new();
686        let p = Parser::new(&v, &mut c);
687        assert_matches!(
688            p.parse(),
689            Err(State::OperandError(DecodeError::StreamExpected(32)))
690        );
691    }
692
693    #[test]
694    fn test_parsing_with_all_optional_operands() {
695        let mut v = ZERO_BOUND_HEADER.to_vec();
696        v.append(&mut vec![0x03, 0x00, 0x05, 0x00]); // OpSource
697        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // GLSL
698        v.append(&mut vec![0xc2, 0x01, 0x00, 0x00]); // 450 (0x1c2)
699        v.append(&mut vec![0x06, 0x00, 0x00, 0x00]); // File id
700        v.append(&mut b"wow".to_vec()); // Source
701        v.push(0x00); // EOS
702        let mut c = RetainingConsumer::new();
703        {
704            let p = Parser::new(&v, &mut c);
705            assert_matches!(p.parse(), Ok(()));
706        }
707        assert_eq!(1, c.insts.len());
708        let inst = &c.insts[0];
709        assert_eq!("Source", inst.class.opname);
710        assert_eq!(None, inst.result_type);
711        assert_eq!(None, inst.result_id);
712        assert_eq!(
713            vec![
714                dr::Operand::SourceLanguage(spirv::SourceLanguage::GLSL),
715                dr::Operand::LiteralBit32(450),
716                dr::Operand::IdRef(6),
717                dr::Operand::from("wow")
718            ],
719            inst.operands
720        );
721    }
722
723    #[test]
724    fn test_parsing_missing_one_optional_operand() {
725        let mut v = ZERO_BOUND_HEADER.to_vec();
726        v.append(&mut vec![0x03, 0x00, 0x04, 0x00]); // OpSource
727        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // GLSL
728        v.append(&mut vec![0xc2, 0x01, 0x00, 0x00]); // 450 (0x1c2)
729        v.append(&mut vec![0x06, 0x00, 0x00, 0x00]); // File id
730        let mut c = RetainingConsumer::new();
731        {
732            let p = Parser::new(&v, &mut c);
733            assert_matches!(p.parse(), Ok(()));
734        }
735        assert_eq!(1, c.insts.len());
736        let inst = &c.insts[0];
737        assert_eq!("Source", inst.class.opname);
738        assert_eq!(None, inst.result_type);
739        assert_eq!(None, inst.result_id);
740        assert_eq!(
741            vec![
742                dr::Operand::SourceLanguage(spirv::SourceLanguage::GLSL),
743                dr::Operand::LiteralBit32(450),
744                dr::Operand::IdRef(6)
745            ],
746            inst.operands
747        );
748    }
749
750    #[test]
751    fn test_parsing_missing_two_optional_operands() {
752        let mut v = ZERO_BOUND_HEADER.to_vec();
753        v.append(&mut vec![0x03, 0x00, 0x03, 0x00]); // OpSource
754        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // GLSL
755        v.append(&mut vec![0xc2, 0x01, 0x00, 0x00]); // 450 (0x1c2)
756        let mut c = RetainingConsumer::new();
757        {
758            let p = Parser::new(&v, &mut c);
759            assert_matches!(p.parse(), Ok(()));
760        }
761        assert_eq!(1, c.insts.len());
762        let inst = &c.insts[0];
763        assert_eq!("Source", inst.class.opname);
764        assert_eq!(None, inst.result_type);
765        assert_eq!(None, inst.result_id);
766        assert_eq!(
767            vec![
768                dr::Operand::SourceLanguage(spirv::SourceLanguage::GLSL),
769                dr::Operand::LiteralBit32(450)
770            ],
771            inst.operands
772        );
773    }
774
775    #[derive(Debug)]
776    struct ErrorString(&'static str);
777    impl error::Error for ErrorString {}
778    impl fmt::Display for ErrorString {
779        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
780            let ErrorString(s) = self;
781            write!(f, "{}", s)
782        }
783    }
784
785    struct InitializeErrorConsumer;
786    impl Consumer for InitializeErrorConsumer {
787        fn initialize(&mut self) -> Action {
788            Action::Error(Box::new(ErrorString("init error")))
789        }
790        fn finalize(&mut self) -> Action {
791            Action::Continue
792        }
793        fn consume_header(&mut self, _: dr::ModuleHeader) -> Action {
794            Action::Continue
795        }
796        fn consume_instruction(&mut self, _: dr::Instruction) -> Action {
797            Action::Continue
798        }
799    }
800
801    #[test]
802    fn test_consumer_initialize_error() {
803        let v = vec![];
804        let mut c = InitializeErrorConsumer {};
805        let p = Parser::new(&v, &mut c);
806        let ret = p.parse();
807        assert_matches!(ret, Err(State::ConsumerError(_)));
808        assert_eq!(
809            "consumer error: init error",
810            format!("{}", ret.unwrap_err())
811        );
812    }
813
814    struct FinalizeErrorConsumer;
815    impl Consumer for FinalizeErrorConsumer {
816        fn initialize(&mut self) -> Action {
817            Action::Continue
818        }
819        fn finalize(&mut self) -> Action {
820            Action::Error(Box::new(ErrorString("fin error")))
821        }
822        fn consume_header(&mut self, _: dr::ModuleHeader) -> Action {
823            Action::Continue
824        }
825        fn consume_instruction(&mut self, _: dr::Instruction) -> Action {
826            Action::Continue
827        }
828    }
829
830    #[test]
831    fn test_consumer_finalize_error() {
832        let mut c = FinalizeErrorConsumer {};
833        let p = Parser::new(ZERO_BOUND_HEADER, &mut c);
834        let ret = p.parse();
835        assert_matches!(ret, Err(State::ConsumerError(_)));
836        assert_eq!("consumer error: fin error", format!("{}", ret.unwrap_err()));
837    }
838
839    struct ParseHeaderErrorConsumer;
840    impl Consumer for ParseHeaderErrorConsumer {
841        fn initialize(&mut self) -> Action {
842            Action::Continue
843        }
844        fn finalize(&mut self) -> Action {
845            Action::Continue
846        }
847        fn consume_header(&mut self, _: dr::ModuleHeader) -> Action {
848            Action::Error(Box::new(ErrorString("parse header error")))
849        }
850        fn consume_instruction(&mut self, _: dr::Instruction) -> Action {
851            Action::Continue
852        }
853    }
854
855    #[test]
856    fn test_consumer_parse_header_error() {
857        let mut c = ParseHeaderErrorConsumer {};
858        let p = Parser::new(ZERO_BOUND_HEADER, &mut c);
859        let ret = p.parse();
860        assert_matches!(ret, Err(State::ConsumerError(_)));
861        assert_eq!(
862            "consumer error: parse header error",
863            format!("{}", ret.unwrap_err())
864        );
865    }
866
867    struct ParseInstErrorConsumer;
868    impl Consumer for ParseInstErrorConsumer {
869        fn initialize(&mut self) -> Action {
870            Action::Continue
871        }
872        fn finalize(&mut self) -> Action {
873            Action::Continue
874        }
875        fn consume_header(&mut self, _: dr::ModuleHeader) -> Action {
876            Action::Continue
877        }
878        fn consume_instruction(&mut self, _: dr::Instruction) -> Action {
879            Action::Error(Box::new(ErrorString("parse inst error")))
880        }
881    }
882
883    #[test]
884    fn test_consumer_parse_inst_error() {
885        let mut b = ModuleBuilder::new();
886        b.inst(spirv::Op::Nop, vec![]);
887        let mut c = ParseInstErrorConsumer {};
888        let p = Parser::new(b.get(), &mut c);
889        let ret = p.parse();
890        assert_matches!(ret, Err(State::ConsumerError(_)));
891        assert_eq!(
892            "consumer error: parse inst error",
893            format!("{}", ret.unwrap_err())
894        );
895    }
896
897    #[test]
898    fn test_parsing_bit32_int() {
899        let mut v = ZERO_BOUND_HEADER.to_vec();
900        v.append(&mut vec![0x15, 0x00, 0x04, 0x00]); // OpTypeInt
901        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result id: 1
902        v.append(&mut vec![0x20, 0x00, 0x00, 0x00]); // 32
903        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // 1 (signed)
904
905        v.append(&mut vec![0x2b, 0x00, 0x04, 0x00]); // OpConstant
906        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
907        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
908        v.append(&mut vec![0x12, 0x34, 0x56, 0x78]);
909        let mut c = RetainingConsumer::new();
910        {
911            let p = Parser::new(&v, &mut c);
912            assert_matches!(p.parse(), Ok(()));
913        }
914        assert_eq!(2, c.insts.len());
915        let inst = &c.insts[1];
916        assert_eq!("Constant", inst.class.opname);
917        assert_eq!(Some(1), inst.result_type);
918        assert_eq!(Some(2), inst.result_id);
919        assert_eq!(vec![dr::Operand::LiteralBit32(0x78563412)], inst.operands);
920    }
921
922    #[test]
923    fn test_parsing_bit64_int() {
924        let mut v = ZERO_BOUND_HEADER.to_vec();
925        v.append(&mut vec![0x15, 0x00, 0x04, 0x00]); // OpTypeInt
926        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result id: 1
927        v.append(&mut vec![0x40, 0x00, 0x00, 0x00]); // 64
928        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // 1 (signed)
929
930        v.append(&mut vec![0x2b, 0x00, 0x05, 0x00]); // OpConstant
931        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
932        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
933        v.append(&mut vec![0x12, 0x34, 0x56, 0x78]);
934        v.append(&mut vec![0x90, 0xab, 0xcd, 0xef]);
935        let mut c = RetainingConsumer::new();
936        {
937            let p = Parser::new(&v, &mut c);
938            assert_matches!(p.parse(), Ok(()));
939        }
940        assert_eq!(2, c.insts.len());
941        let inst = &c.insts[1];
942        assert_eq!("Constant", inst.class.opname);
943        assert_eq!(Some(1), inst.result_type);
944        assert_eq!(Some(2), inst.result_id);
945        assert_eq!(
946            vec![dr::Operand::LiteralBit64(0xefcdab9078563412)],
947            inst.operands
948        );
949    }
950
951    #[test]
952    fn test_parsing_bit32_float() {
953        let mut v = ZERO_BOUND_HEADER.to_vec();
954        v.append(&mut vec![0x16, 0x00, 0x03, 0x00]); // OpTypeFloat
955        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result id: 1
956        v.append(&mut vec![0x20, 0x00, 0x00, 0x00]); // 32
957
958        v.append(&mut vec![0x2b, 0x00, 0x04, 0x00]); // OpConstant
959        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
960        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
961        v.append(&mut vec![0x14, 0xAE, 0x29, 0x42]); // 42.42
962        let mut c = RetainingConsumer::new();
963        {
964            let p = Parser::new(&v, &mut c);
965            assert_matches!(p.parse(), Ok(()));
966        }
967        assert_eq!(2, c.insts.len());
968        let inst = &c.insts[1];
969        assert_eq!("Constant", inst.class.opname);
970        assert_eq!(Some(1), inst.result_type);
971        assert_eq!(Some(2), inst.result_id);
972        assert_eq!(
973            vec![dr::Operand::LiteralBit32(42.42f32.to_bits())],
974            inst.operands
975        );
976    }
977
978    #[test]
979    fn test_parsing_bit64_float() {
980        let mut v = ZERO_BOUND_HEADER.to_vec();
981        v.append(&mut vec![0x16, 0x00, 0x03, 0x00]); // OpTypeFloat
982        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result id: 1
983        v.append(&mut vec![0x40, 0x00, 0x00, 0x00]); // 64
984
985        v.append(&mut vec![0x2b, 0x00, 0x05, 0x00]); // OpConstant
986        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
987        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
988        v.append(&mut vec![0xAE, 0x47, 0xE1, 0x7A, 0x14, 0xAE, 0x28, 0xC0]); // -12.34
989        let mut c = RetainingConsumer::new();
990        {
991            let p = Parser::new(&v, &mut c);
992            assert_matches!(p.parse(), Ok(()));
993        }
994        assert_eq!(2, c.insts.len());
995        let inst = &c.insts[1];
996        assert_eq!("Constant", inst.class.opname);
997        assert_eq!(Some(1), inst.result_type);
998        assert_eq!(Some(2), inst.result_id);
999        assert_eq!(
1000            vec![dr::Operand::LiteralBit64((-12.34f64).to_bits())],
1001            inst.operands
1002        );
1003    }
1004
1005    #[test]
1006    fn test_parsing_spec_constant_op() {
1007        let mut v = ZERO_BOUND_HEADER.to_vec();
1008        v.append(&mut vec![0x34, 0x00, 0x05, 0x00]); // OpTypeFloat
1009        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
1010        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
1011        v.append(&mut vec![0x7e, 0x00, 0x00, 0x00]); // OpSNegate
1012        v.append(&mut vec![0x03, 0x00, 0x00, 0x00]); // id ref: 3
1013        let mut c = RetainingConsumer::new();
1014        {
1015            let p = Parser::new(&v, &mut c);
1016            assert_matches!(p.parse(), Ok(()));
1017        }
1018        assert_eq!(1, c.insts.len());
1019        let inst = &c.insts[0];
1020        assert_eq!("SpecConstantOp", inst.class.opname);
1021        assert_eq!(Some(1), inst.result_type);
1022        assert_eq!(Some(2), inst.result_id);
1023        assert_eq!(
1024            vec![
1025                dr::Operand::LiteralSpecConstantOpInteger(spirv::Op::SNegate),
1026                dr::Operand::IdRef(3)
1027            ],
1028            inst.operands
1029        );
1030    }
1031
1032    #[test]
1033    fn test_parsing_spec_constant_op_missing_parameter() {
1034        let mut v = ZERO_BOUND_HEADER.to_vec();
1035        v.append(&mut vec![0x34, 0x00, 0x05, 0x00]); // OpTypeFloat
1036        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // result type: 1
1037        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // result id: 2
1038        v.append(&mut vec![0x80, 0x00, 0x00, 0x00]); // OpIAdd
1039        v.append(&mut vec![0x03, 0x00, 0x00, 0x00]); // id ref: 3
1040        let mut c = RetainingConsumer::new();
1041        let p = Parser::new(&v, &mut c);
1042        assert_matches!(
1043            p.parse(),
1044            // The header has 5 words, the above instruction has 5 words,
1045            // so in total 40 bytes.
1046            Err(State::OperandError(DecodeError::LimitReached(40)))
1047        );
1048    }
1049
1050    #[test]
1051    fn test_parsing_bitmasks_requiring_params_no_mem_access() {
1052        let mut v = ZERO_BOUND_HEADER.to_vec();
1053        v.append(&mut vec![0x3e, 0x00, 0x03, 0x00]); // OpStore
1054        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // pointer: 1
1055        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // object: 2
1056        let mut c = RetainingConsumer::new();
1057        {
1058            let p = Parser::new(&v, &mut c);
1059            assert_matches!(p.parse(), Ok(()));
1060        }
1061        assert_eq!(1, c.insts.len());
1062        let inst = &c.insts[0];
1063        assert_eq!("Store", inst.class.opname);
1064        assert_eq!(None, inst.result_type);
1065        assert_eq!(None, inst.result_id);
1066        assert_eq!(
1067            vec![dr::Operand::IdRef(1), dr::Operand::IdRef(2)],
1068            inst.operands
1069        );
1070    }
1071    #[test]
1072    fn test_parsing_bitmasks_requiring_params_mem_access_no_param() {
1073        let mut v = ZERO_BOUND_HEADER.to_vec();
1074        v.append(&mut vec![0x3e, 0x00, 0x04, 0x00]); // OpStore
1075        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // pointer: 1
1076        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // object: 2
1077        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // Volatile
1078        let mut c = RetainingConsumer::new();
1079        {
1080            let p = Parser::new(&v, &mut c);
1081            assert_matches!(p.parse(), Ok(()));
1082        }
1083        assert_eq!(1, c.insts.len());
1084        let inst = &c.insts[0];
1085        assert_eq!("Store", inst.class.opname);
1086        assert_eq!(None, inst.result_type);
1087        assert_eq!(None, inst.result_id);
1088        assert_eq!(
1089            vec![
1090                dr::Operand::IdRef(1),
1091                dr::Operand::IdRef(2),
1092                dr::Operand::MemoryAccess(spirv::MemoryAccess::VOLATILE)
1093            ],
1094            inst.operands
1095        );
1096    }
1097    #[test]
1098    fn test_parsing_bitmasks_requiring_params_mem_access_with_param() {
1099        let mut v = ZERO_BOUND_HEADER.to_vec();
1100        v.append(&mut vec![0x3e, 0x00, 0x05, 0x00]); // OpStore
1101        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // pointer: 1
1102        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // object: 2
1103        v.append(&mut vec![0x03, 0x00, 0x00, 0x00]); // Volatile & Aligned
1104        v.append(&mut vec![0x04, 0x00, 0x00, 0x00]); // alignment
1105        let mut c = RetainingConsumer::new();
1106        {
1107            let p = Parser::new(&v, &mut c);
1108            assert_matches!(p.parse(), Ok(()));
1109        }
1110        assert_eq!(1, c.insts.len());
1111        let inst = &c.insts[0];
1112        assert_eq!("Store", inst.class.opname);
1113        assert_eq!(None, inst.result_type);
1114        assert_eq!(None, inst.result_id);
1115        assert_eq!(
1116            vec![
1117                dr::Operand::IdRef(1),
1118                dr::Operand::IdRef(2),
1119                dr::Operand::MemoryAccess(spirv::MemoryAccess::from_bits(3).unwrap()),
1120                dr::Operand::LiteralBit32(4)
1121            ],
1122            inst.operands
1123        );
1124    }
1125    #[test]
1126    fn test_parsing_bitmasks_requiring_params_mem_access_missing_param() {
1127        let mut v = ZERO_BOUND_HEADER.to_vec();
1128        v.append(&mut vec![0x3e, 0x00, 0x04, 0x00]); // OpStore
1129        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // pointer: 1
1130        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // object: 2
1131        v.append(&mut vec![0x03, 0x00, 0x00, 0x00]); // Volatile & Aligned
1132        let mut c = RetainingConsumer::new();
1133        let p = Parser::new(&v, &mut c);
1134        assert_matches!(
1135            p.parse(),
1136            // The header has 5 words, the above instruction has 4 words,
1137            // so in total 36 bytes.
1138            Err(State::OperandError(DecodeError::LimitReached(36)))
1139        );
1140    }
1141    #[test]
1142    fn test_parsing_bitmasks_requiring_params_img_operands_param_order() {
1143        let mut v = ZERO_BOUND_HEADER.to_vec();
1144        v.append(&mut vec![0x63, 0x00, 0x08, 0x00]); // OpStore
1145        v.append(&mut vec![0x01, 0x00, 0x00, 0x00]); // image: 1
1146        v.append(&mut vec![0x02, 0x00, 0x00, 0x00]); // coordinate: 2
1147        v.append(&mut vec![0x03, 0x00, 0x00, 0x00]); // texel: 3
1148        v.append(&mut vec![0x05, 0x00, 0x00, 0x00]); // Bias & GRAD
1149        v.append(&mut vec![0xaa, 0x00, 0x00, 0x00]); // bias
1150        v.append(&mut vec![0xbb, 0x00, 0x00, 0x00]); // dx
1151        v.append(&mut vec![0xcc, 0x00, 0x00, 0x00]); // dy
1152        let mut c = RetainingConsumer::new();
1153        {
1154            let p = Parser::new(&v, &mut c);
1155            assert_matches!(p.parse(), Ok(()));
1156        }
1157        assert_eq!(1, c.insts.len());
1158        let inst = &c.insts[0];
1159        assert_eq!("ImageWrite", inst.class.opname);
1160        assert_eq!(None, inst.result_type);
1161        assert_eq!(None, inst.result_id);
1162        assert_eq!(
1163            vec![
1164                dr::Operand::IdRef(1),
1165                dr::Operand::IdRef(2),
1166                dr::Operand::IdRef(3),
1167                dr::Operand::ImageOperands(spirv::ImageOperands::from_bits(5).unwrap()),
1168                dr::Operand::IdRef(0xaa),
1169                dr::Operand::IdRef(0xbb),
1170                dr::Operand::IdRef(0xcc)
1171            ],
1172            inst.operands
1173        );
1174    }
1175
1176    #[test]
1177    fn test_parse_words() {
1178        let words = vec![0x07230203, 0x01000000, 0, 0, 0, 0x00020011, 0x00000016];
1179        let mut c = RetainingConsumer::new();
1180        assert_matches!(parse_words(&words, &mut c), Ok(()));
1181        assert_eq!(1, c.insts.len());
1182        let inst = &c.insts[0];
1183        assert_eq!("Capability", inst.class.opname);
1184        assert_eq!(None, inst.result_type);
1185        assert_eq!(None, inst.result_id);
1186        assert_eq!(
1187            vec![dr::Operand::Capability(spirv::Capability::Int16)],
1188            inst.operands
1189        );
1190    }
1191}