1 //! Inline instruction arguments. 2 3 /// Support for decoding a sequence of bytes or words from the 4 /// instruction stream. 5 #[derive(Copy, Clone, Default, Debug)] 6 pub struct Args<'a> { 7 bytes: &'a [u8], 8 is_words: bool, 9 } 10 11 impl<'a> Args<'a> { new(bytes: &'a [u8], is_words: bool) -> Self12 pub(crate) fn new(bytes: &'a [u8], is_words: bool) -> Self { 13 Self { bytes, is_words } 14 } 15 16 /// Returns the number of arguments in the list. len(&self) -> usize17 pub fn len(&self) -> usize { 18 if self.is_words { 19 self.bytes.len() / 2 20 } else { 21 self.bytes.len() 22 } 23 } 24 25 /// Returns true if the argument list is empty. is_empty(&self) -> bool26 pub fn is_empty(&self) -> bool { 27 self.bytes.is_empty() 28 } 29 30 /// Returns an iterator over the argument values. values(&self) -> impl Iterator<Item = i32> + 'a + Clone31 pub fn values(&self) -> impl Iterator<Item = i32> + 'a + Clone { 32 let bytes = if self.is_words { &[] } else { self.bytes }; 33 let words = if self.is_words { self.bytes } else { &[] }; 34 bytes 35 .iter() 36 .map(|byte| *byte as u32 as i32) 37 .chain(words.chunks_exact(2).map(|chunk| { 38 let word = ((chunk[0] as u16) << 8) | chunk[1] as u16; 39 // Double cast to ensure sign extension 40 word as i16 as i32 41 })) 42 } 43 } 44 45 /// Mock for testing arguments. 46 #[cfg(test)] 47 pub(crate) struct MockArgs { 48 bytes: Vec<u8>, 49 is_words: bool, 50 } 51 52 #[cfg(test)] 53 impl MockArgs { from_bytes(bytes: &[u8]) -> Self54 pub fn from_bytes(bytes: &[u8]) -> Self { 55 Self { 56 bytes: bytes.into(), 57 is_words: false, 58 } 59 } 60 from_words(words: &[i16]) -> Self61 pub fn from_words(words: &[i16]) -> Self { 62 Self { 63 bytes: words 64 .iter() 65 .map(|word| *word as u16) 66 .flat_map(|word| vec![(word >> 8) as u8, word as u8]) 67 .collect(), 68 is_words: true, 69 } 70 } 71 args(&self) -> Args72 pub fn args(&self) -> Args { 73 Args { 74 bytes: &self.bytes, 75 is_words: self.is_words, 76 } 77 } 78 } 79 80 #[cfg(test)] 81 mod tests { 82 use super::MockArgs; 83 84 #[test] byte_args()85 fn byte_args() { 86 let values = [5, 2, 85, 92, 26, 42, u8::MIN, u8::MAX]; 87 let mock = MockArgs::from_bytes(&values); 88 let decoded = mock.args().values().collect::<Vec<_>>(); 89 assert!(values.iter().map(|x| *x as i32).eq(decoded.iter().copied())); 90 } 91 92 #[test] word_args()93 fn word_args() { 94 let values = [-5, 2, 2845, 92, -26, 42, i16::MIN, i16::MAX]; 95 let mock = MockArgs::from_words(&values); 96 let decoded = mock.args().values().collect::<Vec<_>>(); 97 assert!(values.iter().map(|x| *x as i32).eq(decoded.iter().copied())); 98 } 99 } 100