Add rev jet

This commit is contained in:
Aurimas Blažulionis 2023-03-28 20:48:19 +03:00
parent 4cb2af9bf0
commit c9ff3ce67c
No known key found for this signature in database
GPG Key ID: 8707AB2921774338
3 changed files with 75 additions and 10 deletions

View File

@ -61,6 +61,7 @@ pub fn get_jet(jet_name: Noun) -> Option<Jet> {
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

View File

@ -651,6 +651,41 @@ pub fn met(bloq: usize, a: Atom) -> usize {
}
}
pub fn jet_rev(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
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));
}
}

View File

@ -182,6 +182,10 @@ impl DirectAtom {
pub fn as_bitslice(&self) -> &BitSlice<u64, Lsb0> {
BitSlice::from_element(&self.0)
}
pub fn as_bitslice_mut<'a>(&'a mut self) -> &'a mut BitSlice<u64, Lsb0> {
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<u64, Lsb0> {
BitSlice::from_slice_mut(self.as_mut_slice())
}
pub fn as_ubig<S: Stack>(&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<u64, Lsb0> {
if self.is_indirect() {
unsafe { self.indirect.as_bitslice_mut() }
} else {
unsafe { self.direct.as_bitslice_mut() }
}
}
pub fn as_ubig<S: Stack>(self, stack: &mut S) -> UBig {
if self.is_indirect() {
unsafe { self.indirect.as_ubig(stack) }