1use crate::bytecode_constants::*;
6use crate::compiler::symbol_table::get_deprecated_key_identifier;
7use crate::compiler::Symbol;
8use crate::interpreter::common::*;
9use crate::interpreter::decode_bind_rules::DecodedBindRules;
10use crate::parser::bind_library;
11use core::hash::Hash;
12use num_traits::FromPrimitive;
13use std::collections::HashMap;
14
15#[derive(PartialEq)]
16enum Condition {
17 Unconditional,
18 Equal,
19 Inequal,
20}
21
22#[derive(
26 Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize,
27)]
28pub enum PropertyKey {
29 NumberKey(u64),
30 StringKey(String),
31}
32
33pub type DeviceProperties = HashMap<PropertyKey, Symbol>;
34
35pub struct MatchBindData<'a> {
36 pub symbol_table: &'a HashMap<u32, String>,
37 pub instructions: &'a Vec<u8>,
38}
39
40struct DeviceMatcher<'a> {
41 properties: &'a DeviceProperties,
42 symbol_table: &'a HashMap<u32, String>,
43 iter: BytecodeIter<'a>,
44}
45
46impl<'a> DeviceMatcher<'a> {
47 pub fn match_bind(mut self) -> Result<bool, BytecodeError> {
48 while let Some(byte) = self.iter.next() {
49 let op_byte = FromPrimitive::from_u8(*byte).ok_or(BytecodeError::InvalidOp(*byte))?;
50 match op_byte {
51 RawOp::EqualCondition | RawOp::InequalCondition => {
52 if !self.evaluate_condition_inst(op_byte)? {
53 return Ok(false);
54 }
55 }
56 RawOp::Abort => {
57 return Ok(false);
58 }
59 RawOp::UnconditionalJump => self.evaluate_jump_inst(Condition::Unconditional)?,
60 RawOp::JumpIfEqual => self.evaluate_jump_inst(Condition::Equal)?,
61 RawOp::JumpIfNotEqual => self.evaluate_jump_inst(Condition::Inequal)?,
62 RawOp::JumpLandPad => {
63 }
65 };
66 }
67
68 Ok(true)
69 }
70
71 fn evaluate_condition_inst(&mut self, op: RawOp) -> Result<bool, BytecodeError> {
73 let condition = match op {
74 RawOp::EqualCondition => Condition::Equal,
75 RawOp::InequalCondition => Condition::Inequal,
76 _ => panic!(
77 "evaluate_condition_inst() should only be called for Equal or Inequal instructions"
78 ),
79 };
80
81 Ok(self.read_and_evaluate_values(condition)?)
82 }
83
84 fn evaluate_jump_inst(&mut self, condition: Condition) -> Result<(), BytecodeError> {
85 let offset = next_u32(&mut self.iter)?;
86 if condition != Condition::Unconditional && !self.read_and_evaluate_values(condition)? {
87 return Ok(());
88 }
89
90 for _ in 0..offset {
92 next_u8(&mut self.iter)?;
93 }
94
95 if *next_u8(&mut self.iter)? != RawOp::JumpLandPad as u8 {
97 return Err(BytecodeError::InvalidJumpLocation);
98 }
99
100 Ok(())
101 }
102
103 fn read_and_evaluate_values(&mut self, condition: Condition) -> Result<bool, BytecodeError> {
105 let property_key = match self.read_next_value()? {
106 Symbol::NumberValue(key) => PropertyKey::NumberKey(key),
107 Symbol::StringValue(key) => PropertyKey::StringKey(key),
108 Symbol::Key(key, _) => PropertyKey::StringKey(key),
109 _ => {
110 return Err(BytecodeError::InvalidKeyType);
111 }
112 };
113
114 let expected_value = self.read_next_value()?;
115 let mut node_property_value = self.properties.get(&property_key);
116
117 if node_property_value.is_none() {
121 if let PropertyKey::NumberKey(int_key) = property_key {
122 if let Some(str_key) = get_deprecated_key_identifier(int_key as u32) {
123 node_property_value = self.properties.get(&PropertyKey::StringKey(str_key));
124 }
125 }
126 }
127
128 match node_property_value {
129 None => Ok(condition == Condition::Inequal),
130 Some(value) => compare_symbols(condition, &expected_value, value),
131 }
132 }
133
134 fn read_next_value(&mut self) -> Result<Symbol, BytecodeError> {
137 let value_type = *next_u8(&mut self.iter)?;
138 let value_type = FromPrimitive::from_u8(value_type)
139 .ok_or(BytecodeError::InvalidValueType(value_type))?;
140
141 let value = next_u32(&mut self.iter)?;
142 match value_type {
143 RawValueType::NumberValue => Ok(Symbol::NumberValue(value as u64)),
144 RawValueType::Key => {
145 Ok(Symbol::Key(self.lookup_symbol_table(value)?, bind_library::ValueType::Str))
148 }
149 RawValueType::StringValue => Ok(Symbol::StringValue(self.lookup_symbol_table(value)?)),
150 RawValueType::BoolValue => match value {
151 0x0 => Ok(Symbol::BoolValue(false)),
152 0x1 => Ok(Symbol::BoolValue(true)),
153 _ => Err(BytecodeError::InvalidBoolValue(value)),
154 },
155 RawValueType::EnumValue => Ok(Symbol::EnumValue(self.lookup_symbol_table(value)?)),
156 }
157 }
158
159 fn lookup_symbol_table(&self, key: u32) -> Result<String, BytecodeError> {
160 self.symbol_table
161 .get(&key)
162 .ok_or(BytecodeError::MissingEntryInSymbolTable(key))
163 .map(|val| val.to_string())
164 }
165}
166
167fn compare_symbols(
168 condition: Condition,
169 lhs: &Symbol,
170 rhs: &Symbol,
171) -> Result<bool, BytecodeError> {
172 let mut lhs_for_compare = lhs.clone();
176 let mut rhs_for_compare = rhs.clone();
177 if let Symbol::EnumValue(val) = lhs {
178 lhs_for_compare = Symbol::StringValue(val.to_string());
179 };
180 if let Symbol::EnumValue(val) = rhs {
181 rhs_for_compare = Symbol::StringValue(val.to_string());
182 };
183 if std::mem::discriminant(&lhs_for_compare) != std::mem::discriminant(&rhs_for_compare) {
184 return Err(BytecodeError::MismatchValueTypes);
185 }
186
187 Ok(match condition {
188 Condition::Equal => lhs_for_compare == rhs_for_compare,
189 Condition::Inequal => lhs_for_compare != rhs_for_compare,
190 Condition::Unconditional => {
191 panic!("This function shouldn't be called for Unconditional.")
192 }
193 })
194}
195
196pub fn match_bytecode(
199 bytecode: Vec<u8>,
200 properties: &DeviceProperties,
201) -> Result<bool, BytecodeError> {
202 let decoded_bind_rules = DecodedBindRules::from_bytecode(bytecode)?;
203 let matcher = DeviceMatcher {
204 properties: &properties,
205 symbol_table: &decoded_bind_rules.symbol_table,
206 iter: decoded_bind_rules.instructions.iter(),
207 };
208 matcher.match_bind()
209}
210
211pub fn match_bind(
213 bind_data: MatchBindData,
214 properties: &DeviceProperties,
215) -> Result<bool, BytecodeError> {
216 let matcher = DeviceMatcher {
217 properties: &properties,
218 symbol_table: &bind_data.symbol_table,
219 iter: bind_data.instructions.iter(),
220 };
221 matcher.match_bind()
222}
223
224#[cfg(test)]
225mod test {
226 use super::*;
227
228 const OP_BYTES: u32 = 1;
230 const VALUE_BYTES: u32 = 5;
231 const OFFSET_BYTES: u32 = 4;
232
233 const ABORT_BYTES: u32 = OP_BYTES;
235 const COND_INST_BYTES: u32 = OP_BYTES + VALUE_BYTES + VALUE_BYTES;
236 const UNCOND_JMP_BYTES: u32 = OP_BYTES + OFFSET_BYTES;
237 const COND_JMP_BYTES: u32 = OP_BYTES + OFFSET_BYTES + VALUE_BYTES + VALUE_BYTES;
238 const JMP_PAD_BYTES: u32 = OP_BYTES;
239
240 struct EncodedValue {
241 value_type: RawValueType,
242 value: u32,
243 }
244
245 fn append_encoded_value(bytecode: &mut Vec<u8>, encoded_val: EncodedValue) {
246 bytecode.push(encoded_val.value_type as u8);
247 bytecode.extend_from_slice(&encoded_val.value.to_le_bytes());
248 }
249
250 fn append_abort(bytecode: &mut Vec<u8>) {
251 bytecode.push(0x30);
252 }
253
254 fn append_equal_cond(
255 bytecode: &mut Vec<u8>,
256 property_key: EncodedValue,
257 property_value: EncodedValue,
258 ) {
259 bytecode.push(0x01);
260 append_encoded_value(bytecode, property_key);
261 append_encoded_value(bytecode, property_value);
262 }
263
264 fn append_inequal_cond(
265 bytecode: &mut Vec<u8>,
266 property_key: EncodedValue,
267 property_value: EncodedValue,
268 ) {
269 bytecode.push(0x02);
270 append_encoded_value(bytecode, property_key);
271 append_encoded_value(bytecode, property_value);
272 }
273
274 fn append_unconditional_jump(bytecode: &mut Vec<u8>, offset: u32) {
275 bytecode.push(0x10);
276 bytecode.extend_from_slice(&offset.to_le_bytes());
277 }
278
279 fn append_jump_if_equal(
280 bytecode: &mut Vec<u8>,
281 offset: u32,
282 property_key: EncodedValue,
283 property_value: EncodedValue,
284 ) {
285 bytecode.push(0x11);
286 bytecode.extend_from_slice(&offset.to_le_bytes());
287 append_encoded_value(bytecode, property_key);
288 append_encoded_value(bytecode, property_value);
289 }
290
291 fn append_jump_if_not_equal(
292 bytecode: &mut Vec<u8>,
293 offset: u32,
294 property_key: EncodedValue,
295 property_value: EncodedValue,
296 ) {
297 bytecode.push(0x12);
298 bytecode.extend_from_slice(&offset.to_le_bytes());
299 append_encoded_value(bytecode, property_key);
300 append_encoded_value(bytecode, property_value);
301 }
302
303 fn append_jump_pad(bytecode: &mut Vec<u8>) {
304 bytecode.push(0x20);
305 }
306
307 fn verify_match_result(
308 expected_result: Result<bool, BytecodeError>,
309 bind_rules: DecodedBindRules,
310 device_properties: &DeviceProperties,
311 ) {
312 let matcher = DeviceMatcher {
313 properties: device_properties,
314 symbol_table: &bind_rules.symbol_table,
315 iter: bind_rules.instructions.iter(),
316 };
317
318 assert_eq!(expected_result, matcher.match_bind());
319 }
320
321 #[test]
322 fn empty_instructions() {
323 verify_match_result(
324 Ok(true),
325 DecodedBindRules {
326 symbol_table: HashMap::new(),
327 instructions: vec![],
328 decoded_instructions: vec![],
329 debug_info: None,
330 },
331 &HashMap::new(),
332 );
333 }
334
335 #[test]
336 fn equal_condition_with_number_property_keys() {
337 let mut device_properties: DeviceProperties = HashMap::new();
338 device_properties.insert(PropertyKey::NumberKey(1), Symbol::NumberValue(2000));
339 device_properties.insert(PropertyKey::NumberKey(2), Symbol::NumberValue(500));
340
341 let mut instructions: Vec<u8> = vec![];
343 append_equal_cond(
344 &mut instructions,
345 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
346 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
347 );
348 verify_match_result(
349 Ok(true),
350 DecodedBindRules {
351 symbol_table: HashMap::new(),
352 instructions: instructions,
353 decoded_instructions: vec![],
354 debug_info: None,
355 },
356 &device_properties,
357 );
358
359 let mut instructions: Vec<u8> = vec![];
361 append_equal_cond(
362 &mut instructions,
363 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
364 EncodedValue { value_type: RawValueType::NumberValue, value: 5 },
365 );
366 verify_match_result(
367 Ok(false),
368 DecodedBindRules {
369 symbol_table: HashMap::new(),
370 instructions: instructions,
371 decoded_instructions: vec![],
372 debug_info: None,
373 },
374 &device_properties,
375 );
376
377 let mut instructions: Vec<u8> = vec![];
379 append_equal_cond(
380 &mut instructions,
381 EncodedValue { value_type: RawValueType::NumberValue, value: 3 },
382 EncodedValue { value_type: RawValueType::NumberValue, value: 5 },
383 );
384 verify_match_result(
385 Ok(false),
386 DecodedBindRules {
387 symbol_table: HashMap::new(),
388 instructions: instructions,
389 decoded_instructions: vec![],
390 debug_info: None,
391 },
392 &device_properties,
393 );
394 }
395
396 #[test]
397 fn equal_condition_with_string_property_keys() {
398 let mut device_properties: DeviceProperties = HashMap::new();
399 device_properties.insert(
400 PropertyKey::StringKey("nightjar".to_string()),
401 Symbol::StringValue("poorwill".to_string()),
402 );
403
404 device_properties.insert(
405 PropertyKey::StringKey("poorwill".to_string()),
406 Symbol::EnumValue("nighthawk".to_string()),
407 );
408
409 let mut symbol_table: HashMap<u32, String> = HashMap::new();
410 symbol_table.insert(1, "nightjar".to_string());
411 symbol_table.insert(2, "poorwill".to_string());
412 symbol_table.insert(3, "nighthawk".to_string());
413
414 let mut instructions: Vec<u8> = vec![];
416 append_equal_cond(
417 &mut instructions,
418 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
419 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
420 );
421 append_equal_cond(
422 &mut instructions,
423 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
424 EncodedValue { value_type: RawValueType::EnumValue, value: 3 },
425 );
426 verify_match_result(
427 Ok(true),
428 DecodedBindRules {
429 symbol_table: symbol_table.clone(),
430 instructions: instructions,
431 decoded_instructions: vec![],
432 debug_info: None,
433 },
434 &device_properties,
435 );
436
437 let mut instructions: Vec<u8> = vec![];
439 append_equal_cond(
440 &mut instructions,
441 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
442 EncodedValue { value_type: RawValueType::StringValue, value: 3 },
443 );
444 verify_match_result(
445 Ok(false),
446 DecodedBindRules {
447 symbol_table: symbol_table.clone(),
448 instructions: instructions,
449 decoded_instructions: vec![],
450 debug_info: None,
451 },
452 &device_properties,
453 );
454
455 let mut instructions: Vec<u8> = vec![];
457 append_equal_cond(
458 &mut instructions,
459 EncodedValue { value_type: RawValueType::StringValue, value: 3 },
460 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
461 );
462 verify_match_result(
463 Ok(false),
464 DecodedBindRules {
465 symbol_table: symbol_table.clone(),
466 instructions: instructions,
467 decoded_instructions: vec![],
468 debug_info: None,
469 },
470 &device_properties,
471 );
472 }
473
474 #[test]
475 fn inequal_condition_with_number_property_keys() {
476 let mut device_properties: DeviceProperties = HashMap::new();
477 device_properties.insert(PropertyKey::NumberKey(1), Symbol::NumberValue(2000));
478 device_properties.insert(PropertyKey::NumberKey(2), Symbol::NumberValue(500));
479
480 let mut instructions: Vec<u8> = vec![];
482 append_inequal_cond(
483 &mut instructions,
484 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
485 EncodedValue { value_type: RawValueType::NumberValue, value: 500 },
486 );
487 verify_match_result(
488 Ok(true),
489 DecodedBindRules {
490 symbol_table: HashMap::new(),
491 instructions: instructions,
492 decoded_instructions: vec![],
493 debug_info: None,
494 },
495 &device_properties,
496 );
497
498 let mut instructions: Vec<u8> = vec![];
500 append_inequal_cond(
501 &mut instructions,
502 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
503 EncodedValue { value_type: RawValueType::NumberValue, value: 5 },
504 );
505 verify_match_result(
506 Ok(true),
507 DecodedBindRules {
508 symbol_table: HashMap::new(),
509 instructions: instructions,
510 decoded_instructions: vec![],
511 debug_info: None,
512 },
513 &device_properties,
514 );
515
516 let mut instructions: Vec<u8> = vec![];
518 append_inequal_cond(
519 &mut instructions,
520 EncodedValue { value_type: RawValueType::NumberValue, value: 2 },
521 EncodedValue { value_type: RawValueType::NumberValue, value: 500 },
522 );
523 verify_match_result(
524 Ok(false),
525 DecodedBindRules {
526 symbol_table: HashMap::new(),
527 instructions: instructions,
528 decoded_instructions: vec![],
529 debug_info: None,
530 },
531 &device_properties,
532 );
533 }
534
535 #[test]
536 fn inequal_condition_with_string_property_keys() {
537 let mut device_properties: DeviceProperties = HashMap::new();
538 device_properties.insert(
539 PropertyKey::StringKey("nightjar".to_string()),
540 Symbol::StringValue("poorwill".to_string()),
541 );
542
543 let mut symbol_table: HashMap<u32, String> = HashMap::new();
544 symbol_table.insert(1, "nightjar".to_string());
545 symbol_table.insert(2, "poorwill".to_string());
546
547 let mut instructions: Vec<u8> = vec![];
549 append_inequal_cond(
550 &mut instructions,
551 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
552 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
553 );
554 verify_match_result(
555 Ok(true),
556 DecodedBindRules {
557 symbol_table: symbol_table.clone(),
558 instructions: instructions,
559 decoded_instructions: vec![],
560 debug_info: None,
561 },
562 &device_properties,
563 );
564
565 let mut instructions: Vec<u8> = vec![];
568 append_inequal_cond(
569 &mut instructions,
570 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
571 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
572 );
573 verify_match_result(
574 Ok(true),
575 DecodedBindRules {
576 symbol_table: symbol_table.clone(),
577 instructions: instructions,
578 decoded_instructions: vec![],
579 debug_info: None,
580 },
581 &device_properties,
582 );
583
584 let mut instructions: Vec<u8> = vec![];
586 append_inequal_cond(
587 &mut instructions,
588 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
589 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
590 );
591 verify_match_result(
592 Ok(false),
593 DecodedBindRules {
594 symbol_table: symbol_table.clone(),
595 instructions: instructions,
596 decoded_instructions: vec![],
597 debug_info: None,
598 },
599 &device_properties,
600 );
601 }
602
603 #[test]
604 fn unconditional_abort() {
605 let mut instructions: Vec<u8> = vec![];
606 append_abort(&mut instructions);
607 verify_match_result(
608 Ok(false),
609 DecodedBindRules {
610 symbol_table: HashMap::new(),
611 instructions: instructions,
612 decoded_instructions: vec![],
613 debug_info: None,
614 },
615 &HashMap::new(),
616 );
617 }
618
619 #[test]
620 fn match_with_key_values() {
621 let mut device_properties: DeviceProperties = HashMap::new();
622 device_properties
623 .insert(PropertyKey::StringKey("timberdoodle".to_string()), Symbol::NumberValue(2000));
624
625 let mut symbol_table: HashMap<u32, String> = HashMap::new();
626 symbol_table.insert(1, "timberdoodle".to_string());
627
628 let mut instructions: Vec<u8> = vec![];
629 append_equal_cond(
630 &mut instructions,
631 EncodedValue { value_type: RawValueType::Key, value: 1 },
632 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
633 );
634 verify_match_result(
635 Ok(true),
636 DecodedBindRules {
637 symbol_table: symbol_table.clone(),
638 instructions: instructions,
639 decoded_instructions: vec![],
640 debug_info: None,
641 },
642 &device_properties,
643 );
644
645 let mut instructions: Vec<u8> = vec![];
646 append_equal_cond(
647 &mut instructions,
648 EncodedValue { value_type: RawValueType::Key, value: 1 },
649 EncodedValue { value_type: RawValueType::NumberValue, value: 500 },
650 );
651 verify_match_result(
652 Ok(false),
653 DecodedBindRules {
654 symbol_table: symbol_table,
655 instructions: instructions,
656 decoded_instructions: vec![],
657 debug_info: None,
658 },
659 &device_properties,
660 );
661 }
662
663 #[test]
664 fn match_with_bool_values() {
665 let mut device_properties: DeviceProperties = HashMap::new();
666 device_properties.insert(PropertyKey::NumberKey(1), Symbol::BoolValue(true));
667
668 let mut instructions: Vec<u8> = vec![];
669 append_equal_cond(
670 &mut instructions,
671 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
672 EncodedValue { value_type: RawValueType::BoolValue, value: 1 },
673 );
674 verify_match_result(
675 Ok(true),
676 DecodedBindRules {
677 symbol_table: HashMap::new(),
678 instructions: instructions,
679 decoded_instructions: vec![],
680 debug_info: None,
681 },
682 &device_properties,
683 );
684
685 let mut instructions: Vec<u8> = vec![];
686 append_equal_cond(
687 &mut instructions,
688 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
689 EncodedValue { value_type: RawValueType::BoolValue, value: 0 },
690 );
691 verify_match_result(
692 Ok(false),
693 DecodedBindRules {
694 symbol_table: HashMap::new(),
695 instructions: instructions,
696 decoded_instructions: vec![],
697 debug_info: None,
698 },
699 &device_properties,
700 );
701 }
702
703 #[test]
704 fn match_with_str_deprecated_keys() {
705 let mut device_properties: DeviceProperties = HashMap::new();
706 device_properties.insert(
707 PropertyKey::StringKey("fuchsia.BIND_PROTOCOL".to_string()),
708 Symbol::NumberValue(10),
709 );
710 device_properties.insert(
711 PropertyKey::StringKey("fuchsia.BIND_PWM_ID".to_string()),
712 Symbol::NumberValue(5),
713 );
714
715 let mut instructions: Vec<u8> = vec![];
716 append_equal_cond(
717 &mut instructions,
718 EncodedValue {
719 value_type: RawValueType::NumberValue,
720 value: 0x01, },
722 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
723 );
724 append_equal_cond(
725 &mut instructions,
726 EncodedValue {
727 value_type: RawValueType::NumberValue,
728 value: 0x0A50, },
730 EncodedValue { value_type: RawValueType::NumberValue, value: 5 },
731 );
732 verify_match_result(
733 Ok(true),
734 DecodedBindRules {
735 symbol_table: HashMap::new(),
736 instructions: instructions,
737 decoded_instructions: vec![],
738 debug_info: None,
739 },
740 &device_properties,
741 );
742 }
743
744 #[test]
745 fn missing_entry_in_symbol_table() {
746 let mut symbol_table: HashMap<u32, String> = HashMap::new();
747 symbol_table.insert(1, "nightjar".to_string());
748 symbol_table.insert(2, "poorwill".to_string());
749
750 let mut instructions: Vec<u8> = vec![];
751 append_inequal_cond(
752 &mut instructions,
753 EncodedValue { value_type: RawValueType::StringValue, value: 10 },
754 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
755 );
756 verify_match_result(
757 Err(BytecodeError::MissingEntryInSymbolTable(10)),
758 DecodedBindRules {
759 symbol_table: HashMap::new(),
760 instructions: instructions,
761 decoded_instructions: vec![],
762 debug_info: None,
763 },
764 &HashMap::new(),
765 );
766
767 let mut instructions: Vec<u8> = vec![];
768 append_inequal_cond(
769 &mut instructions,
770 EncodedValue { value_type: RawValueType::Key, value: 15 },
771 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
772 );
773 verify_match_result(
774 Err(BytecodeError::MissingEntryInSymbolTable(15)),
775 DecodedBindRules {
776 symbol_table: HashMap::new(),
777 instructions: instructions,
778 decoded_instructions: vec![],
779 debug_info: None,
780 },
781 &HashMap::new(),
782 );
783 }
784
785 #[test]
786 fn invalid_op() {
787 let mut instructions: Vec<u8> = vec![0xFF];
788 append_inequal_cond(
789 &mut instructions,
790 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
791 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
792 );
793
794 verify_match_result(
795 Err(BytecodeError::InvalidOp(0xFF)),
796 DecodedBindRules {
797 symbol_table: HashMap::new(),
798 instructions: instructions,
799 decoded_instructions: vec![],
800 debug_info: None,
801 },
802 &HashMap::new(),
803 );
804 }
805
806 #[test]
807 fn invalid_value_type() {
808 let instructions: Vec<u8> = vec![0x01, 0x05, 0, 0, 0, 0, 0x01, 0, 0, 0, 0];
809 verify_match_result(
810 Err(BytecodeError::InvalidValueType(0x05)),
811 DecodedBindRules {
812 symbol_table: HashMap::new(),
813 instructions: instructions,
814 decoded_instructions: vec![],
815 debug_info: None,
816 },
817 &HashMap::new(),
818 );
819 }
820
821 #[test]
822 fn invalid_bool_value() {
823 let mut instructions: Vec<u8> = vec![];
824 append_inequal_cond(
825 &mut instructions,
826 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
827 EncodedValue { value_type: RawValueType::BoolValue, value: 15 },
828 );
829
830 verify_match_result(
831 Err(BytecodeError::InvalidBoolValue(15)),
832 DecodedBindRules {
833 symbol_table: HashMap::new(),
834 instructions: instructions,
835 decoded_instructions: vec![],
836 debug_info: None,
837 },
838 &HashMap::new(),
839 );
840 }
841
842 #[test]
843 fn invalid_key_type() {
844 let mut instructions: Vec<u8> = vec![];
845 append_inequal_cond(
846 &mut instructions,
847 EncodedValue { value_type: RawValueType::BoolValue, value: 1 },
848 EncodedValue { value_type: RawValueType::BoolValue, value: 15 },
849 );
850
851 verify_match_result(
852 Err(BytecodeError::InvalidKeyType),
853 DecodedBindRules {
854 symbol_table: HashMap::new(),
855 instructions: instructions,
856 decoded_instructions: vec![],
857 debug_info: None,
858 },
859 &HashMap::new(),
860 );
861 }
862
863 #[test]
864 fn mismatch_value_types() {
865 let mut device_properties: DeviceProperties = HashMap::new();
866 device_properties.insert(PropertyKey::NumberKey(1), Symbol::NumberValue(2000));
867 device_properties.insert(
868 PropertyKey::StringKey("tyrant".to_string()),
869 Symbol::StringValue("flycatcher".to_string()),
870 );
871
872 let mut symbol_table: HashMap<u32, String> = HashMap::new();
873 symbol_table.insert(1, "tyrant".to_string());
874 symbol_table.insert(2, "flycatcher".to_string());
875
876 let mut instructions: Vec<u8> = vec![];
877 append_equal_cond(
878 &mut instructions,
879 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
880 EncodedValue { value_type: RawValueType::NumberValue, value: 15 },
881 );
882
883 verify_match_result(
884 Err(BytecodeError::MismatchValueTypes),
885 DecodedBindRules {
886 symbol_table: symbol_table,
887 instructions: instructions,
888 decoded_instructions: vec![],
889 debug_info: None,
890 },
891 &device_properties,
892 );
893 }
894
895 #[test]
896 fn invalid_condition_statement() {
897 let instructions: Vec<u8> = vec![0x01, 0x02, 0, 0, 0];
898 verify_match_result(
899 Err(BytecodeError::UnexpectedEnd),
900 DecodedBindRules {
901 symbol_table: HashMap::new(),
902 instructions: instructions,
903 decoded_instructions: vec![],
904 debug_info: None,
905 },
906 &HashMap::new(),
907 );
908 }
909
910 #[test]
911 fn match_with_multiple_condition_statements() {
912 let mut device_properties: DeviceProperties = HashMap::new();
913 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
914 device_properties.insert(PropertyKey::NumberKey(2), Symbol::NumberValue(500));
915 device_properties.insert(
916 PropertyKey::StringKey("rail".to_string()),
917 Symbol::StringValue("crake".to_string()),
918 );
919
920 let mut symbol_table: HashMap<u32, String> = HashMap::new();
921 symbol_table.insert(1, "crake".to_string());
922 symbol_table.insert(2, "rail".to_string());
923
924 let mut instructions: Vec<u8> = vec![];
925 append_inequal_cond(
926 &mut instructions,
927 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
928 EncodedValue { value_type: RawValueType::NumberValue, value: 200 },
929 );
930 append_inequal_cond(
931 &mut instructions,
932 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
933 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
934 );
935 append_equal_cond(
936 &mut instructions,
937 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
938 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
939 );
940
941 verify_match_result(
942 Ok(true),
943 DecodedBindRules {
944 symbol_table: symbol_table,
945 instructions: instructions,
946 decoded_instructions: vec![],
947 debug_info: None,
948 },
949 &device_properties,
950 );
951 }
952
953 #[test]
954 fn no_match_with_multiple_condition_statements() {
955 let mut device_properties: DeviceProperties = HashMap::new();
956 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
957 device_properties.insert(PropertyKey::NumberKey(2), Symbol::NumberValue(500));
958 device_properties.insert(
959 PropertyKey::StringKey("rail".to_string()),
960 Symbol::StringValue("crake".to_string()),
961 );
962
963 let mut symbol_table: HashMap<u32, String> = HashMap::new();
964 symbol_table.insert(1, "crake".to_string());
965 symbol_table.insert(2, "rail".to_string());
966
967 let mut instructions: Vec<u8> = vec![];
968 append_equal_cond(
969 &mut instructions,
970 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
971 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
972 );
973 append_equal_cond(
974 &mut instructions,
975 EncodedValue { value_type: RawValueType::NumberValue, value: 2 },
976 EncodedValue { value_type: RawValueType::NumberValue, value: 5000 },
977 );
978 append_inequal_cond(
979 &mut instructions,
980 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
981 EncodedValue { value_type: RawValueType::NumberValue, value: 40 },
982 );
983
984 verify_match_result(
985 Ok(false),
986 DecodedBindRules {
987 symbol_table: symbol_table,
988 instructions: instructions,
989 decoded_instructions: vec![],
990 debug_info: None,
991 },
992 &device_properties,
993 );
994 }
995
996 #[test]
997 fn unconditional_jump() {
998 let mut instructions: Vec<u8> = vec![];
999 append_unconditional_jump(&mut instructions, ABORT_BYTES + COND_INST_BYTES);
1000 append_abort(&mut instructions);
1001 append_equal_cond(
1002 &mut instructions,
1003 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
1004 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1005 );
1006 append_jump_pad(&mut instructions);
1007
1008 verify_match_result(
1009 Ok(true),
1010 DecodedBindRules {
1011 symbol_table: HashMap::new(),
1012 instructions: instructions,
1013 decoded_instructions: vec![],
1014 debug_info: None,
1015 },
1016 &HashMap::new(),
1017 );
1018 }
1019
1020 #[test]
1021 fn jump_if_equal() {
1022 let mut symbol_table: HashMap<u32, String> = HashMap::new();
1023 symbol_table.insert(1, "whimbrel".to_string());
1024
1025 let mut instructions: Vec<u8> = vec![];
1026 append_jump_if_equal(
1027 &mut instructions,
1028 ABORT_BYTES * 2,
1029 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
1030 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
1031 );
1032 append_abort(&mut instructions);
1033 append_abort(&mut instructions);
1034 append_jump_pad(&mut instructions);
1035
1036 let mut device_properties: DeviceProperties = HashMap::new();
1037 device_properties
1038 .insert(PropertyKey::NumberKey(10), Symbol::StringValue("whimbrel".to_string()));
1039 verify_match_result(
1040 Ok(true),
1041 DecodedBindRules {
1042 symbol_table: symbol_table.clone(),
1043 instructions: instructions.clone(),
1044 decoded_instructions: vec![],
1045 debug_info: None,
1046 },
1047 &device_properties,
1048 );
1049
1050 let mut device_properties: DeviceProperties = HashMap::new();
1051 device_properties
1052 .insert(PropertyKey::NumberKey(10), Symbol::StringValue("godwit".to_string()));
1053 verify_match_result(
1054 Ok(false),
1055 DecodedBindRules {
1056 symbol_table: symbol_table.clone(),
1057 instructions: instructions,
1058 decoded_instructions: vec![],
1059 debug_info: None,
1060 },
1061 &device_properties,
1062 );
1063 }
1064
1065 #[test]
1066 fn jump_if_not_equal() {
1067 let mut instructions: Vec<u8> = vec![];
1068 append_jump_if_not_equal(
1069 &mut instructions,
1070 ABORT_BYTES * 2,
1071 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
1072 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1073 );
1074 append_abort(&mut instructions);
1075 append_abort(&mut instructions);
1076 append_jump_pad(&mut instructions);
1077
1078 let mut device_properties: DeviceProperties = HashMap::new();
1079 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
1080 verify_match_result(
1081 Ok(false),
1082 DecodedBindRules {
1083 symbol_table: HashMap::new(),
1084 instructions: instructions.clone(),
1085 decoded_instructions: vec![],
1086 debug_info: None,
1087 },
1088 &device_properties,
1089 );
1090
1091 let mut device_properties: DeviceProperties = HashMap::new();
1092 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(20));
1093 verify_match_result(
1094 Ok(true),
1095 DecodedBindRules {
1096 symbol_table: HashMap::new(),
1097 instructions: instructions,
1098 decoded_instructions: vec![],
1099 debug_info: None,
1100 },
1101 &device_properties,
1102 );
1103 }
1104
1105 #[test]
1106 fn no_jump_pad() {
1107 let mut device_properties: DeviceProperties = HashMap::new();
1108 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
1109
1110 let mut instructions: Vec<u8> = vec![];
1111 append_jump_if_equal(
1112 &mut instructions,
1113 ABORT_BYTES,
1114 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
1115 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1116 );
1117 append_abort(&mut instructions);
1118 append_abort(&mut instructions);
1119 verify_match_result(
1120 Err(BytecodeError::InvalidJumpLocation),
1121 DecodedBindRules {
1122 symbol_table: HashMap::new(),
1123 instructions: instructions,
1124 decoded_instructions: vec![],
1125 debug_info: None,
1126 },
1127 &device_properties,
1128 );
1129 }
1130
1131 #[test]
1132 fn jump_out_of_bounds() {
1133 let mut device_properties: DeviceProperties = HashMap::new();
1134 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
1135
1136 let mut instructions: Vec<u8> = vec![];
1137 append_jump_if_equal(
1138 &mut instructions,
1139 ABORT_BYTES + JMP_PAD_BYTES + 1,
1140 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
1141 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1142 );
1143 append_abort(&mut instructions);
1144 append_jump_pad(&mut instructions);
1145 verify_match_result(
1146 Err(BytecodeError::UnexpectedEnd),
1147 DecodedBindRules {
1148 symbol_table: HashMap::new(),
1149 instructions: instructions,
1150 decoded_instructions: vec![],
1151 debug_info: None,
1152 },
1153 &device_properties,
1154 );
1155 }
1156
1157 #[test]
1158 fn nested_jump_instructions() {
1159 let mut instructions: Vec<u8> = vec![];
1160 append_jump_if_equal(
1161 &mut instructions,
1162 ABORT_BYTES * 2 + UNCOND_JMP_BYTES + JMP_PAD_BYTES,
1163 EncodedValue { value_type: RawValueType::NumberValue, value: 10 },
1164 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1165 );
1166 append_unconditional_jump(&mut instructions, ABORT_BYTES);
1167 append_abort(&mut instructions);
1168 append_jump_pad(&mut instructions);
1169 append_abort(&mut instructions);
1170 append_jump_pad(&mut instructions);
1171
1172 let mut device_properties: DeviceProperties = HashMap::new();
1173 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(2000));
1174 verify_match_result(
1175 Ok(true),
1176 DecodedBindRules {
1177 symbol_table: HashMap::new(),
1178 instructions: instructions.clone(),
1179 decoded_instructions: vec![],
1180 debug_info: None,
1181 },
1182 &device_properties,
1183 );
1184
1185 let mut device_properties: DeviceProperties = HashMap::new();
1186 device_properties.insert(PropertyKey::NumberKey(10), Symbol::NumberValue(200));
1187 device_properties.insert(
1188 PropertyKey::StringKey("kingfisher".to_string()),
1189 Symbol::StringValue("kookaburra".to_string()),
1190 );
1191 verify_match_result(
1192 Ok(false),
1193 DecodedBindRules {
1194 symbol_table: HashMap::new(),
1195 instructions: instructions,
1196 decoded_instructions: vec![],
1197 debug_info: None,
1198 },
1199 &device_properties,
1200 );
1201 }
1202
1203 #[test]
1204 fn complex_mix_of_bind_rules() {
1205 let mut symbol_table: HashMap<u32, String> = HashMap::new();
1206 symbol_table.insert(1, "kingfisher".to_string());
1207 symbol_table.insert(2, "kookaburra".to_string());
1208
1209 let mut instructions: Vec<u8> = vec![];
1210 append_jump_if_equal(
1211 &mut instructions,
1212 COND_INST_BYTES + ABORT_BYTES,
1213 EncodedValue { value_type: RawValueType::NumberValue, value: 5 },
1214 EncodedValue { value_type: RawValueType::BoolValue, value: 1 },
1215 );
1216 append_equal_cond(
1217 &mut instructions,
1218 EncodedValue { value_type: RawValueType::NumberValue, value: 2 },
1219 EncodedValue { value_type: RawValueType::NumberValue, value: 2000 },
1220 );
1221 append_abort(&mut instructions);
1222 append_jump_pad(&mut instructions);
1223 append_unconditional_jump(&mut instructions, COND_JMP_BYTES + ABORT_BYTES);
1224 append_jump_if_not_equal(
1225 &mut instructions,
1226 ABORT_BYTES + JMP_PAD_BYTES + COND_INST_BYTES,
1227 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
1228 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
1229 );
1230 append_abort(&mut instructions);
1231 append_jump_pad(&mut instructions);
1232 append_inequal_cond(
1233 &mut instructions,
1234 EncodedValue { value_type: RawValueType::NumberValue, value: 1 },
1235 EncodedValue { value_type: RawValueType::NumberValue, value: 50 },
1236 );
1237 append_jump_pad(&mut instructions);
1238 append_equal_cond(
1239 &mut instructions,
1240 EncodedValue { value_type: RawValueType::StringValue, value: 1 },
1241 EncodedValue { value_type: RawValueType::StringValue, value: 2 },
1242 );
1243
1244 let mut device_properties: DeviceProperties = HashMap::new();
1245 device_properties.insert(
1246 PropertyKey::StringKey("kingfisher".to_string()),
1247 Symbol::StringValue("kookaburra".to_string()),
1248 );
1249 device_properties.insert(PropertyKey::NumberKey(1), Symbol::NumberValue(9));
1250 device_properties.insert(PropertyKey::NumberKey(2), Symbol::NumberValue(100));
1251 device_properties.insert(PropertyKey::NumberKey(5), Symbol::BoolValue(true));
1252
1253 verify_match_result(
1254 Ok(true),
1255 DecodedBindRules {
1256 symbol_table: symbol_table,
1257 instructions: instructions,
1258 decoded_instructions: vec![],
1259 debug_info: None,
1260 },
1261 &device_properties,
1262 );
1263 }
1264}