diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 0000000000000000000000000000000000000000..13db9eedd91d8c6ff8974cf0d2cf96f5d257c5b4 --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,122 @@ +use core::ops::{Deref, DerefMut}; + +#[derive(Debug)] +pub struct BufferOverflow; + +#[derive(Debug)] +pub struct Buffer<'a, const N: usize> { + data: &'a mut [u8; N], + i: usize, +} + +impl<'a, const N: usize> Buffer<'a, N> { + /// Constructs a new `Buffer`. + /// `data` is the backing array. + /// `i` is the number of elements in `data` that contain data (and should thus be exposed by `Buffer`) + pub fn new(data: &'a mut [u8; N], i: usize) -> Self { + assert!(i <= data.len()); + + Self { data, i } + } + + pub fn new_full(data: &'a mut [u8; N]) -> Self { + let i = data.len(); + + Self::new(data, i) + } + + pub fn new_empty(data: &'a mut [u8; N]) -> Self { + Self::new(data, 0) + } + + pub const fn remaining_capacity(&self) -> usize { + N - self.i + } + + pub fn try_push(&mut self, v: u8) -> Result<(), BufferOverflow> { + if self.i == N { + return Err(BufferOverflow); + } + + self.data[self.i] = v; + self.i += 1; + + Ok(()) + } + + pub fn push(&mut self, v: u8) { + self.try_push(v).unwrap(); + } + + pub fn try_extend_from_slice(&mut self, other: &[u8]) -> Result<(), BufferOverflow> { + if self.remaining_capacity() < other.len() { + return Err(BufferOverflow); + } + + self.data[self.i..(self.i + other.len())].copy_from_slice(other); + self.i += other.len(); + + Ok(()) + } + + pub fn extend(&mut self, other: &[u8]) { + self.try_extend_from_slice(other).unwrap(); + } + + pub fn pop(&mut self) -> Option<u8> { + if self.i == 0 { + return None; + } + + self.i -= 1; + + Some(self.data[self.i]) + } + + pub fn truncate(&mut self, new_len: usize) { + assert!(self.i >= new_len); + + self.i = new_len; + } + + pub fn drain(&mut self, start: usize, end: usize) { + assert!(end >= start); + assert!(end <= self.i); + let delta = end - start; + let surplus = self.len() - end; + + for i in start..(start + surplus) { + self[i] = self[i + delta]; + } + + self.i -= delta; + } + + pub fn clone_backing<'b>(&self, buf: &'b mut [u8; N]) -> Buffer<'b, N> { + let mut out = Buffer::new_empty(buf); + + out.extend(self); + + out + } +} + +impl<'a, const N: usize> From<&'a mut [u8; N]> for Buffer<'a, N> { + fn from(data: &'a mut [u8; N]) -> Self { + Self { data, i: 0 } + } +} + +impl<'a, const N: usize> Deref for Buffer<'a, N> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.data[..self.i] + } +} + +impl<'a, const N: usize> DerefMut for Buffer<'a, N> { + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.data[..self.i] + } +} diff --git a/src/interleaver.rs b/src/interleaver.rs index 5661bb43b2b90d526157167c4ad8f5718984f806..5efeaaf7a3fdded2468749e22dd88dfe01383ff0 100644 --- a/src/interleaver.rs +++ b/src/interleaver.rs @@ -1,11 +1,13 @@ -use arrayvec::{ArrayVec, CapacityError}; use bitvec::prelude::*; -use crate::error::EncodeError; +use crate::{ + buffer::{Buffer, BufferOverflow}, + error::EncodeError, +}; pub(crate) fn interleave<const N: usize>( data: &[u8], - out: &mut ArrayVec<u8, N>, + out: &mut Buffer<N>, ) -> Result<(), EncodeError> { let bv = data.view_bits::<Msb0>(); @@ -33,10 +35,10 @@ pub(crate) fn interleave<const N: usize>( pub(crate) fn uninterleave<const N: usize>( data: &[u8], -) -> Result<ArrayVec<u8, N>, CapacityError<u8>> { + out: &mut Buffer<N>, +) -> Result<(), BufferOverflow> { let bv = data.view_bits::<Msb0>(); - let mut out: ArrayVec<u8, N> = ArrayVec::new(); for _ in 0..data.len() { out.try_push(0)?; } @@ -55,7 +57,7 @@ pub(crate) fn uninterleave<const N: usize>( } } - Ok(out) + Ok(()) } #[cfg(test)] @@ -64,17 +66,22 @@ mod tests { #[test] fn interleaver_works() { - let orig = - ArrayVec::try_from([0x84, 0x73, 0x12, 0xA3, 0xFF, 0x00, 0xC2, 0x1B, 0x77]).unwrap(); - let mut interleaved: ArrayVec<u8, 10> = ArrayVec::new(); + let mut data = [0x84, 0x73, 0x12, 0xA3, 0xFF, 0x00, 0xC2, 0x1B, 0x77]; + let orig = Buffer::new_full(&mut data); + + let mut interleaved = [0; 10]; + let mut interleaved = Buffer::new(&mut interleaved, 0); interleaved.push(b'H'); + interleave(&orig, &mut interleaved).unwrap(); let expected = [b'H', 0xCD, 0xB5, 0xDB, 0x2A, 0x0A, 0x52, 0x0C, 0x89, 0x4F]; assert_eq!(expected, interleaved[..]); - let uninterleaved = uninterleave(&interleaved[1..]).unwrap(); + let mut uninterleaved = [0; 10]; + let mut uninterleaved = Buffer::new(&mut uninterleaved, 0); + uninterleave(&interleaved[1..], &mut uninterleaved).unwrap(); - assert_eq!(orig, uninterleaved); + assert_eq!(*orig, *uninterleaved); } } diff --git a/src/ldpc.rs b/src/ldpc.rs index d085bf4a6269b2c757539918e73680444e8eedc9..a3cda75036ccfb1cadf6a4159707913c59198dc5 100644 --- a/src/ldpc.rs +++ b/src/ldpc.rs @@ -1,7 +1,6 @@ -use arrayvec::ArrayVec; use labrador_ldpc::LDPCCode; -use crate::error::EncodeError; +use crate::{buffer::Buffer, error::EncodeError}; macro_rules! enc_chunk { ($d:ident, $i:ident, $t:ident, $n:literal) => { @@ -38,7 +37,7 @@ macro_rules! dec_chunk { } // On failure this still modifies the data array! -pub(crate) fn encode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Result<(), EncodeError> { +pub(crate) fn encode<const N: usize>(data: &mut Buffer<N>) -> Result<(), EncodeError> { let mut i = 0; let n = data.len(); @@ -84,7 +83,7 @@ pub(crate) fn encode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Result<(), E Ok(()) } -pub(crate) fn decode<const N: usize>(data_av: &mut ArrayVec<u8, N>) -> Option<()> { +pub(crate) fn decode<const N: usize>(data_av: &mut Buffer<N>) -> Option<()> { if data_av.len() < 2 { return None; } @@ -157,25 +156,18 @@ pub(crate) fn decode<const N: usize>(data_av: &mut ArrayVec<u8, N>) -> Option<() #[cfg(test)] mod tests { use super::*; - use arrayvec::ArrayVec; #[test] fn len_test() { // from the example in the docs - let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); + let mut buf = [0; 8191]; + let mut data = Buffer::new_empty(&mut buf); for _ in 0..41 { - data.extend( - b"Example packet data wueirpqwerwrywqoeiruy29346129384761" - .iter() - .cloned(), - ); + data.extend(b"Example packet data wueirpqwerwrywqoeiruy29346129384761"); } - data.extend( - b"Example packet data wueirpqwerwrywqoeiru346129384761" - .iter() - .cloned(), - ); + data.extend(b"Example packet data wueirpqwerwrywqoeiru346129384761"); + assert_eq!(2349, data.len()); encode(&mut data).unwrap(); @@ -185,51 +177,50 @@ mod tests { #[test] fn basic_encode_decode_short() { - let mut data: ArrayVec<u8, 32> = ArrayVec::new(); + let mut buf = [0; 32]; + let mut buf2 = [0; 32]; + let mut data = Buffer::new_empty(&mut buf); data.try_extend_from_slice(b"Hello world!").unwrap(); - let orig = data.clone(); + let orig = data.clone_backing(&mut buf2); encode(&mut data).unwrap(); decode(&mut data).unwrap(); - assert_eq!(orig, data); + assert_eq!(*orig, *data); } #[test] fn basic_encode_decode() { - let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); + let mut buf = [0; 8191]; + let mut buf2 = [0; 8191]; + let mut data = Buffer::new_empty(&mut buf); for _ in 0..50 { - data.extend( - b"This is a test packet. jsalksjd093809324JASLD:LKD*#$)(*#@)" - .iter() - .cloned(), - ); + data.extend(b"This is a test packet. jsalksjd093809324JASLD:LKD*#$)(*#@)"); } - let orig = data.clone(); + let orig = data.clone_backing(&mut buf2); encode(&mut data).unwrap(); - assert_ne!(orig, data); + assert_ne!(*orig, *data); decode(&mut data).unwrap(); - assert_eq!(orig, data); + assert_eq!(*orig, *data); } #[test] fn encode_decode_with_bit_flips() { - let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); + let mut buf = [0; 8191]; + let mut buf2 = [0; 8191]; + let mut data = Buffer::new_empty(&mut buf); + for _ in 0..50 { - data.extend( - b"jsalksjd093809324JASLD:LKD*#$)(*#@) Another test packet" - .iter() - .cloned(), - ); + data.extend(b"jsalksjd093809324JASLD:LKD*#$)(*#@) Another test packet"); } - let orig = data.clone(); + let orig = data.clone_backing(&mut buf2); encode(&mut data).unwrap(); - assert_ne!(orig, data); + assert_ne!(*orig, *data); data[234] ^= 0x55; data[0] ^= 0xAA; @@ -237,6 +228,6 @@ mod tests { decode(&mut data).unwrap(); - assert_eq!(orig, data); + assert_eq!(*orig, *data); } } diff --git a/src/lib.rs b/src/lib.rs index 79eebf023d26c464a8773b0a66dd14b975024ef7..feeaa23f790c92af2322ee1727132f366bdddb0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] +pub mod buffer; pub mod error; pub mod interleaver; pub mod ldpc; diff --git a/src/packet.rs b/src/packet.rs index a671484362d1b2a41148797b844eaca62a7bcc9f..6ad9e01630fde26843aff00f211de96a43497099 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,9 +1,9 @@ use core::fmt::Debug; -use arrayvec::{ArrayVec, CapacityError}; use crc::{Crc, CRC_16_IBM_SDLC}; use crate::{ + buffer::{Buffer, BufferOverflow}, error::{CommentError, DecodeError, EncodeError}, interleaver, ldpc, utf8, whisker::{ @@ -30,7 +30,7 @@ macro_rules! uniq_whisker { return Err(EncodeError::DuplicateData); } - try_lock(&mut self.data, |data| { + try_lock(&mut self.buf, |data| { let mut buf = [0; 256]; // safe to unwrap since we know we have enough space let out = w.encode(&mut buf).unwrap(); @@ -66,7 +66,7 @@ macro_rules! poly_whisker { } pub fn [<add_ $t:lower>](&mut self, w: $t) -> Result<(), EncodeError> { - try_lock(&mut self.data, |data| { + try_lock(&mut self.buf, |data| { let mut buf = [0; 256]; // safe to unwrap since we know we have enough space let out = w.encode(&mut buf).unwrap(); @@ -89,22 +89,32 @@ macro_rules! poly_whisker { /// N is the maximum packet size we can handle /// Panics if N >= 8191 -#[derive(Default, Clone)] -pub struct Packet<const N: usize> { - data: ArrayVec<u8, N>, +pub struct Packet<'a, const N: usize> { + buf: Buffer<'a, N>, } -// TODO need to have methods for removing whiskers from the packet -impl<const N: usize> Packet<N> { - pub fn decode(data: ArrayVec<u8, N>) -> Result<Self, DecodeError> { +impl<'a, const N: usize> Packet<'a, N> { + pub fn new(buf: &'a mut [u8; N]) -> Self { + Self { buf: buf.into() } + } + + pub fn clone_backing<'b>(&self, buf: &'b mut [u8; N]) -> Packet<'b, N> { + Packet { + buf: self.buf.clone_backing(buf), + } + } + + /// Expects bytes in the `buf` + /// `buf` is used as the backing buffer for the Packet + pub fn decode(buf: Buffer<'a, N>) -> Result<Self, DecodeError> { assert!(N <= 8191); // validate the data - for w in WhiskerIter::new(&data) { + for w in WhiskerIter::new(&buf) { w?; } - let comment_iter = WhiskerIter::new(&data) + let comment_iter = WhiskerIter::new(&buf) .filter_map(|w| match w.unwrap() { Whisker::Comment(c) => Some(c.internal_data().clone()), _ => None, @@ -115,18 +125,18 @@ impl<const N: usize> Packet<N> { return Err(DecodeError::InvalidComment); } - Ok(Self { data }) + Ok(Self { buf }) } pub fn encode(&self) -> &[u8] { - &self.data + &self.buf } /// Directly after the CRC block in The Pipeline - pub fn semi_encode(mut self) -> Result<ArrayVec<u8, N>, (EncodeError, Self)> { - let crc = X25.checksum(&self.data).to_le_bytes(); + pub fn semi_encode(mut self) -> Result<Buffer<'a, N>, (EncodeError, Self)> { + let crc = X25.checksum(&self.buf).to_le_bytes(); - let res: Result<(), CapacityError<u8>> = try_lock(&mut self.data, |data| { + let res: Result<(), BufferOverflow> = try_lock(&mut self.buf, |data| { data.try_push(crc[0])?; data.try_push(crc[1])?; @@ -134,52 +144,57 @@ impl<const N: usize> Packet<N> { }); match res { - Ok(()) => Ok(self.data), + Ok(()) => Ok(self.buf), Err(_) => Err((EncodeError::CatsOverflow, self)), } } /// Directly after the CRC block in The Pipeline - pub fn semi_decode(mut data: ArrayVec<u8, N>) -> Result<Self, DecodeError> { - let crc1 = data.pop().ok_or(DecodeError::UnexpectedEndOfInput)?; - let crc0 = data.pop().ok_or(DecodeError::UnexpectedEndOfInput)?; + /// Expects bytes in the `buf` + /// `buf` is used as the backing buffer for the Packet + pub fn semi_decode(mut buf: Buffer<'a, N>) -> Result<Self, DecodeError> { + let crc1 = buf.pop().ok_or(DecodeError::UnexpectedEndOfInput)?; + let crc0 = buf.pop().ok_or(DecodeError::UnexpectedEndOfInput)?; let crc_expected = u16::from_le_bytes([crc0, crc1]); - let crc_actual = X25.checksum(&data); + let crc_actual = X25.checksum(&buf); if crc_expected != crc_actual { return Err(DecodeError::CrcMismatch); } - Self::decode(data) + Self::decode(buf) } /// Encodes packet for transmission on the air. /// Includes the data length L, but does not include the preamble or sync word. - pub fn fully_encode(self) -> Result<ArrayVec<u8, N>, EncodeError> { + pub fn fully_encode(self, out: &mut Buffer<N>) -> Result<(), EncodeError> { let mut data = self.semi_encode().map_err(|(err, _)| err)?; whitener::whiten(&mut data); ldpc::encode(&mut data)?; - let mut out: ArrayVec<u8, N> = ArrayVec::new(); + // safe to unwrap - length must be below 8191 out.try_extend_from_slice(&u16::try_from(data.len()).unwrap().to_le_bytes()) .map_err(|_| EncodeError::CatsOverflow)?; - interleaver::interleave(&data, &mut out)?; + interleaver::interleave(&data, out)?; - Ok(out) + Ok(()) } /// Decodes packet that was received over the air. /// Packet shouldn't have preamble, sync word, or data langth L. - pub fn fully_decode(data: &[u8]) -> Result<Self, DecodeError> { - let mut data = interleaver::uninterleave(data).map_err(|_| DecodeError::Overflow)?; - ldpc::decode(&mut data).ok_or(DecodeError::LdpcError)?; - whitener::whiten(&mut data); - - Self::semi_decode(data) + /// Expects bytes in the `buf` + /// `buf` is used as the backing buffer for the Packet + pub fn fully_decode(data: &[u8], buf: &'a mut [u8; N]) -> Result<Self, DecodeError> { + let mut buf = Buffer::new_empty(buf); + interleaver::uninterleave(data, &mut buf).map_err(|_| DecodeError::Overflow)?; + ldpc::decode(&mut buf).ok_or(DecodeError::LdpcError)?; + whitener::whiten(&mut buf); + + Self::semi_decode(buf) } pub fn iter(&self) -> ValidatedWhiskerIter { - ValidatedWhiskerIter::new(&self.data) + ValidatedWhiskerIter::new(&self.buf) } uniq_whisker!(Identification); @@ -189,7 +204,7 @@ impl<const N: usize> Packet<N> { poly_whisker!(Destination); poly_whisker!(Arbitrary); - pub fn comment<'a>(&self, buf: &'a mut [u8]) -> Result<&'a str, CommentError> { + pub fn comment<'b>(&self, buf: &'b mut [u8]) -> Result<&'b str, CommentError> { let iter = self.iter().filter_map(|w| match w { Whisker::Comment(c) => Some(c), _ => None, @@ -221,7 +236,7 @@ impl<const N: usize> Packet<N> { return Err(EncodeError::DuplicateData); } - try_lock(&mut self.data, |data| { + try_lock(&mut self.buf, |data| { let mut comment = comment.as_bytes(); while comment.len() > 255 { @@ -258,12 +273,12 @@ impl<const N: usize> Packet<N> { fn clear_by_type(&mut self, whisker_type: u8, all: bool) { let mut i = 0; - while i < self.data.len() { - let t = self.data[i]; - let step = usize::from(self.data[i + 1]) + 2; + while i < self.buf.len() { + let t = self.buf[i]; + let step = usize::from(self.buf[i + 1]) + 2; if t == whisker_type { - self.data.drain(i..(i + step)); + self.buf.drain(i, i + step); if !all { return; @@ -275,26 +290,26 @@ impl<const N: usize> Packet<N> { } } -impl<const N: usize> Debug for Packet<N> { +impl<'a, const N: usize> Debug for Packet<'a, N> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_list() - .entries(ValidatedWhiskerIter::new(&self.data)) + .entries(ValidatedWhiskerIter::new(&self.buf)) .finish() } } // if the function returns an error, we roll back the array // by rolling it back, we really just pop bytes off the end until the length matches -fn try_lock<const N: usize, T, E, F: Fn(&mut ArrayVec<u8, N>) -> Result<T, E>>( - arr: &mut ArrayVec<u8, N>, +fn try_lock<'a, const N: usize, T, E, F: Fn(&mut Buffer<'a, N>) -> Result<T, E>>( + buf: &mut Buffer<'a, N>, f: F, ) -> Result<T, E> { - let len = arr.len(); + let len = buf.len(); - match f(arr) { + match f(buf) { Ok(x) => Ok(x), Err(e) => { - arr.truncate(len); + buf.truncate(len); Err(e) } @@ -303,7 +318,7 @@ fn try_lock<const N: usize, T, E, F: Fn(&mut ArrayVec<u8, N>) -> Result<T, E>>( #[cfg(test)] mod tests { - use arrayvec::ArrayString; + use arrayvec::{ArrayString, ArrayVec}; use super::*; @@ -312,7 +327,8 @@ mod tests { let d1 = Destination::new(false, 7, "CALL1", 23).unwrap(); let d2 = Destination::new(true, 23, "CALL2", 2).unwrap(); - let mut packet: Packet<1024> = Packet::default(); + let mut buf = [0; 1024]; + let mut packet: Packet<1024> = Packet::new(&mut buf); packet.add_destination(d1.clone()).unwrap(); packet.add_destination(d2.clone()).unwrap(); @@ -324,7 +340,8 @@ mod tests { #[test] fn route_clear() { - let mut p: Packet<1024> = Packet::default(); + let mut buf = [0; 1024]; + let mut p: Packet<1024> = Packet::new(&mut buf); p.add_identification(Identification::new(123, "call", 43).unwrap()) .unwrap(); let mut r = Route::new(8); @@ -347,7 +364,8 @@ mod tests { fn semi_e2e() { let comment = "Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker."; - let mut packet = Packet::<2048>::default(); + let mut buf = [0; 2048]; + let mut packet = Packet::new(&mut buf); packet .add_identification(Identification { icon: 123, @@ -385,7 +403,8 @@ mod tests { fn full_e2e() { let comment = "Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker."; - let mut packet = Packet::<4096>::default(); + let mut buf = [0; 4096]; + let mut packet = Packet::new(&mut buf); packet .add_identification(Identification { icon: 123, @@ -403,13 +422,16 @@ mod tests { }); assert!(matches!(res, Err(EncodeError::DuplicateData))); - let mut fully = packet.fully_encode().unwrap(); + let mut buf2 = [0; 4096]; + let mut fully = Buffer::new_empty(&mut buf2); + packet.fully_encode(&mut fully).unwrap(); fully[40] ^= 0x55; fully[844] ^= 0x7B; // exclude length - let packet2: Packet<8191> = Packet::fully_decode(&fully[2..]).unwrap(); + let mut buf3 = [0; 8191]; + let packet2: Packet<8191> = Packet::fully_decode(&fully[2..], &mut buf3).unwrap(); assert_eq!( Identification { icon: 123, @@ -476,7 +498,8 @@ mod tests { 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 96, 96, ]; - let _ = Packet::<1024>::fully_decode(&data); + let mut buf = [0; 1024]; + let _ = Packet::<1024>::fully_decode(&data, &mut buf); } #[test] @@ -524,13 +547,15 @@ mod tests { ) .unwrap(); - let _ = Packet::<1024>::semi_decode(data); + let mut buf = [0; 1024]; + let _ = Packet::<1024>::fully_decode(&data, &mut buf); } #[test] fn decode_fuzz_tests() { - let data = ArrayVec::try_from(&[4, 0, 0, 0][..]).unwrap(); + let data = [4, 0, 0, 0]; - let _ = Packet::<1024>::decode(data); + let mut buf = [0; 1024]; + let _ = Packet::<1024>::fully_decode(&data, &mut buf); } } diff --git a/src/whitener.rs b/src/whitener.rs index 46123fe9902a969ed061c6c7004a7576af503526..79d21d97d4a8fa58b6bc6c616e3041fdbd560b77 100644 --- a/src/whitener.rs +++ b/src/whitener.rs @@ -1,10 +1,8 @@ -use arrayvec::ArrayVec; - const WHITE: [u8; 16] = [ 0xe9, 0xcf, 0x67, 0x20, 0x19, 0x1a, 0x07, 0xdc, 0xc0, 0x72, 0x79, 0x97, 0x51, 0xf7, 0xdd, 0x93, ]; -pub(crate) fn whiten<const N: usize>(data: &mut ArrayVec<u8, N>) { +pub(crate) fn whiten(data: &mut [u8]) { for (i, d) in data.iter_mut().enumerate() { *d ^= WHITE[i % 15]; } @@ -16,9 +14,9 @@ mod tests { #[test] fn basic() { - let mut data: ArrayVec<u8, 512> = - ArrayVec::try_from(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]) - .unwrap(); + let mut data = [0; 64]; + data[0..57] + .clone_from_slice(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]); let orig = data.clone(); whiten(&mut data);