From c9ff3ce67cce47f83177fec9cb5f7dbed35cd7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurimas=20Bla=C5=BEulionis?= <0x60@pm.me> Date: Tue, 28 Mar 2023 20:48:19 +0300 Subject: [PATCH] Add rev jet --- rust/ares/src/jets.rs | 1 + rust/ares/src/jets/math.rs | 46 ++++++++++++++++++++++++++++++++++++++ rust/ares/src/noun.rs | 38 ++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 354b8ad..85534f7 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -61,6 +61,7 @@ pub fn get_jet(jet_name: Noun) -> Option { tas!(b"rip") => Some(jet_rip), tas!(b"met") => Some(jet_met), tas!(b"mug") => Some(jet_mug), + tas!(b"rev") => Some(jet_rev), _ => { // eprintln!("Unknown jet: {:?}", jet_name); None diff --git a/rust/ares/src/jets/math.rs b/rust/ares/src/jets/math.rs index 222d7da..5190cfe 100644 --- a/rust/ares/src/jets/math.rs +++ b/rust/ares/src/jets/math.rs @@ -651,6 +651,41 @@ pub fn met(bloq: usize, a: Atom) -> usize { } } +pub fn jet_rev(stack: &mut NockStack, subject: Noun) -> Result { + let arg = raw_slot(subject, 6); + let boz = raw_slot(arg, 2).as_atom()?.as_direct()?.data(); + + if boz >= 64 { + return Err(NonDeterministic); + } + + let boz = boz as usize; + + let len = raw_slot(arg, 6).as_atom()?.as_direct()?.data(); + + let dat = raw_slot(arg, 7).as_atom()?; + + let bits = len << boz; + + let mut output = if dat.is_direct() && bits < 64 { + unsafe { DirectAtom::new_unchecked(0).as_atom() } + } else { + unsafe { IndirectAtom::new_raw(stack, ((bits + 7) / 8) as usize, &0).as_atom() } + }; + + let src = dat.as_bitslice(); + let dest = output.as_bitslice_mut(); + + let len = len as usize; + let total_len = len << boz; + + for (start, end) in (0..len).map(|b| (b << boz, (b + 1) << boz)) { + dest[start..end].copy_from_bitslice(&src[(total_len - end)..(total_len - start)]); + } + + Ok(output.as_noun()) +} + #[cfg(test)] mod tests { use super::*; @@ -1292,4 +1327,15 @@ mod tests { let sam = T(s, &[sam, a0, a24, a63, a96, a128]); assert_jet(s, jet_mug, sam, D(0x7543cac7)); } + + #[test] + fn test_rev() { + let ref mut s = init(); + let (_a0, a24, _a63, a96, a128) = atoms(s); + let sam = T(s, &[D(0), D(60), a24]); + assert_jet(s, jet_rev, sam, D(0xc2a6e1000000000)); + let test = 0x1234567890123u64; + let sam = T(s, &[D(3), D(7), D(test)]); + assert_jet(s, jet_rev, sam, D(test.swap_bytes() >> 8)); + } } diff --git a/rust/ares/src/noun.rs b/rust/ares/src/noun.rs index 068c4a4..3dca704 100644 --- a/rust/ares/src/noun.rs +++ b/rust/ares/src/noun.rs @@ -182,6 +182,10 @@ impl DirectAtom { pub fn as_bitslice(&self) -> &BitSlice { BitSlice::from_element(&self.0) } + + pub fn as_bitslice_mut<'a>(&'a mut self) -> &'a mut BitSlice { + BitSlice::from_element_mut(&mut self.0) + } } impl fmt::Display for DirectAtom { @@ -372,10 +376,18 @@ impl IndirectAtom { unsafe { self.to_raw_pointer().add(2) as *const u64 } } + pub fn data_pointer_mut(&mut self) -> *mut u64 { + unsafe { self.to_raw_pointer_mut().add(2) as *mut u64 } + } + pub fn as_slice(&self) -> &[u64] { unsafe { from_raw_parts(self.data_pointer(), self.size()) } } + pub fn as_mut_slice(&mut self) -> &mut [u64] { + unsafe { from_raw_parts_mut(self.data_pointer_mut(), self.size()) } + } + pub fn as_bytes(&self) -> &[u8] { unsafe { from_raw_parts(self.data_pointer() as *const u8, self.size() << 3) } } @@ -385,6 +397,10 @@ impl IndirectAtom { BitSlice::from_slice(self.as_slice()) } + pub fn as_bitslice_mut<'a>(&'a mut self) -> &'a mut BitSlice { + BitSlice::from_slice_mut(self.as_mut_slice()) + } + pub fn as_ubig(&self, stack: &mut S) -> UBig { UBig::from_le_bytes_stack(stack, self.as_bytes()) } @@ -595,16 +611,10 @@ impl Atom { let bit_size = big.bit_len(); let buffer = big.to_le_bytes_stack(); if bit_size < 64 { - #[rustfmt::skip] - let value: u64 = - if bit_size == 0 { 0 } else { (buffer[0] as u64) - | if bit_size <= 8 { 0 } else { (buffer[1] as u64) << 8 - | if bit_size <= 16 { 0 } else { (buffer[2] as u64) << 16 - | if bit_size <= 24 { 0 } else { (buffer[3] as u64) << 24 - | if bit_size <= 32 { 0 } else { (buffer[4] as u64) << 32 - | if bit_size <= 40 { 0 } else { (buffer[5] as u64) << 40 - | if bit_size <= 48 { 0 } else { (buffer[6] as u64) << 48 - | if bit_size <= 56 { 0 } else { (buffer[7] as u64) << 56 } } } } } } } }; + let mut value = 0u64; + for i in (0..bit_size).step_by(8) { + value |= (buffer[i / 8] as u64) << i; + } unsafe { DirectAtom::new_unchecked(value).as_atom() } } else { let byte_size = (big.bit_len() + 7) >> 3; @@ -652,6 +662,14 @@ impl Atom { } } + pub fn as_bitslice_mut<'a>(&'a mut self) -> &'a mut BitSlice { + if self.is_indirect() { + unsafe { self.indirect.as_bitslice_mut() } + } else { + unsafe { self.direct.as_bitslice_mut() } + } + } + pub fn as_ubig(self, stack: &mut S) -> UBig { if self.is_indirect() { unsafe { self.indirect.as_ubig(stack) }