diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 927b0a8..92ec53e 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -44,6 +44,7 @@ pub fn get_jet(jet_name: Noun) -> Result { tas!(b"rsh") => Ok(jet_rsh), tas!(b"con") => Ok(jet_con), tas!(b"dis") => Ok(jet_dis), + tas!(b"mix") => Ok(jet_mix), tas!(b"cut") => Ok(jet_cut), tas!(b"met") => Ok(jet_met), tas!(b"mug") => Ok(jet_mug), diff --git a/rust/ares/src/jets/math.rs b/rust/ares/src/jets/math.rs index 6ca948d..95cfc3f 100644 --- a/rust/ares/src/jets/math.rs +++ b/rust/ares/src/jets/math.rs @@ -394,6 +394,22 @@ pub fn jet_dis(stack: &mut NockStack, subject: Noun) -> Result { } } +pub fn jet_mix(stack: &mut NockStack, subject: Noun) -> Result { + let arg = raw_slot(subject, 6); + let a = raw_slot(arg, 2).as_atom()?; + let b = raw_slot(arg, 3).as_atom()?; + + let new_size = cmp::max(a.size(), b.size()); + + unsafe { + let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, new_size); + let a_bit = a.as_bitslice(); + dest[..a_bit.len()].copy_from_bitslice(a_bit); + *dest ^= b.as_bitslice(); + Ok(atom.normalize_as_atom().as_noun()) + } +} + pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; @@ -925,6 +941,28 @@ mod tests { assert_math_jet_noun(s, jet_dis, &[atom_128, atom_0], a0); } + #[test] + fn test_mix() { + let ref mut s = init(); + let (_a0, _a24, _a63, _a96, a128) = atoms(s); + assert_math_jet(s, jet_mix, &[atom_0, atom_0], ubig!(0)); + assert_math_jet( + s, + jet_mix, + &[atom_24, atom_96], + ubig!(0xfaceb00c15deadbeef955115), + ); + assert_math_jet( + s, + jet_mix, + &[atom_96, atom_128], + ubig!(0xdeadbeefe8fae674eb02172699460646), + ); + assert_math_jet(s, jet_mix, &[atom_24, atom_63], ubig!(0x7fffffffff789abc)); + assert_math_jet_noun(s, jet_mix, &[atom_0, atom_128], a128); + assert_math_jet_noun(s, jet_mix, &[atom_128, atom_0], a128); + } + #[test] fn test_cut() { let ref mut s = init();