use std::io::{Error, ErrorKind};
use std::{iter, mem};
pub const CRYPTO_PACKET_BUFFER_SIZE: u32 = 32768;
fn real_index(index: u32) -> usize {
(index % CRYPTO_PACKET_BUFFER_SIZE) as usize
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PacketsArray<T> {
pub buffer: Vec<Option<Box<T>>>,
pub buffer_start: u32,
pub buffer_end: u32,
}
impl<T: Clone> PacketsArray<T> {
pub fn new() -> PacketsArray<T> {
PacketsArray {
buffer: iter::repeat(None).take(CRYPTO_PACKET_BUFFER_SIZE as usize).collect(),
buffer_start: 0,
buffer_end: 0,
}
}
}
impl<T> PacketsArray<T> {
pub fn len(&self) -> u32 {
self.buffer_end.overflowing_sub(self.buffer_start).0
}
pub fn insert(&mut self, index: u32, packet: T) -> Result<(), Error> {
if index.overflowing_sub(self.buffer_start).0 >= CRYPTO_PACKET_BUFFER_SIZE {
return Err(Error::new(
ErrorKind::Other,
format!("The index {} is too big and can't be hold", index)
))
}
let i = real_index(index);
if self.buffer[i].is_some() {
return Err(Error::new(
ErrorKind::Other,
format!("The packet with index {} already exists", index)
))
}
self.buffer[i] = Some(Box::new(packet));
if index.overflowing_sub(self.buffer_start).0 >= self.len() {
self.buffer_end = index.overflowing_add(1).0;
}
Ok(())
}
pub fn push_back(&mut self, packet: T) -> Result<(), Error> {
if self.len() == CRYPTO_PACKET_BUFFER_SIZE {
return Err(Error::new(
ErrorKind::Other,
"Packets array is full"
))
}
self.buffer[real_index(self.buffer_end)] = Some(Box::new(packet));
self.buffer_end = self.buffer_end.overflowing_add(1).0;
Ok(())
}
pub fn pop_front(&mut self) -> Option<T> {
if self.buffer_start == self.buffer_end {
return None
}
let i = real_index(self.buffer_start);
if self.buffer[i].is_none() {
return None
}
let result = mem::replace(&mut self.buffer[i], None);
self.buffer_start = self.buffer_start.overflowing_add(1).0;
result.map(|packet| *packet)
}
pub fn get(&self, index: u32) -> Option<&T> {
let len = self.len();
if self.buffer_end.overflowing_sub(index).0 > len || index.overflowing_sub(self.buffer_start).0 >= len {
return None
}
self.buffer[real_index(index)].as_ref().map(|packet| &**packet)
}
pub fn get_mut(&mut self, index: u32) -> Option<&mut T> {
let len = self.len();
if self.buffer_end.overflowing_sub(index).0 > len || index.overflowing_sub(self.buffer_start).0 >= len {
return None
}
self.buffer[real_index(index)].as_mut().map(|packet| &mut **packet)
}
pub fn remove(&mut self, index: u32) -> Option<T> {
let len = self.len();
if self.buffer_end.overflowing_sub(index).0 > len || index.overflowing_sub(self.buffer_start).0 >= len {
return None
}
mem::replace(&mut self.buffer[real_index(index)], None).map(|packet| *packet)
}
pub fn set_buffer_end(&mut self, index: u32) -> Result<(), Error> {
if index.overflowing_sub(self.buffer_start).0 > CRYPTO_PACKET_BUFFER_SIZE {
return Err(Error::new(
ErrorKind::Other,
format!("The index {} is too big and can't be hold", index)
))
}
if index.overflowing_sub(self.buffer_end).0 > CRYPTO_PACKET_BUFFER_SIZE {
return Err(Error::new(
ErrorKind::Other,
format!("Index {} is lower than the end index", index)
))
}
self.buffer_end = index;
Ok(())
}
pub fn set_buffer_start(&mut self, index: u32) -> Result<(), Error> {
let len = self.len();
if self.buffer_end.overflowing_sub(index).0 > len || index.overflowing_sub(self.buffer_start).0 > len {
return Err(Error::new(
ErrorKind::Other,
format!("Index {} is outside of buffer bounds", index)
))
}
for packet in &mut self.buffer[real_index(self.buffer_start) .. real_index(index)] {
*packet = None;
}
self.buffer_start = index;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn len() {
let mut array = PacketsArray::<()>::new();
assert_eq!(array.len(), 0);
array.buffer_end = 1;
assert_eq!(array.len(), 1);
array.buffer_start = u32::max_value();
assert_eq!(array.len(), 2);
}
#[test]
fn insert() {
let mut array = PacketsArray::<()>::new();
assert!(array.insert(0, ()).is_ok());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 1);
assert!(array.get(0).is_some());
assert!(array.get(1).is_none());
assert!(array.insert(7, ()).is_ok());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 8);
assert!(array.get(7).is_some());
assert!(array.get(6).is_none());
assert!(array.get(8).is_none());
}
#[test]
fn insert_exists() {
let mut array = PacketsArray::<()>::new();
assert!(array.insert(7, ()).is_ok());
assert!(array.insert(7, ()).is_err());
assert!(array.insert(6, ()).is_ok());
assert!(array.insert(8, ()).is_ok());
}
#[test]
fn insert_too_big_index() {
let mut array = PacketsArray::<()>::new();
assert!(array.insert(CRYPTO_PACKET_BUFFER_SIZE, ()).is_err());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 0);
array.buffer_start = u32::max_value();
assert!(array.insert(CRYPTO_PACKET_BUFFER_SIZE - 1, ()).is_err());
assert_eq!(array.buffer_start, u32::max_value());
assert_eq!(array.buffer_end, 0);
}
#[test]
fn push_back() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 1);
assert!(array.get(0).is_some());
}
#[test]
fn push_back_overflow() {
let mut array = PacketsArray::<()>::new();
array.buffer_start = u32::max_value();
array.buffer_end = u32::max_value();
assert!(array.push_back(()).is_ok());
assert_eq!(array.buffer_start, u32::max_value());
assert_eq!(array.buffer_end, 0);
assert!(array.get(u32::max_value()).is_some());
}
#[test]
fn push_back_full() {
let mut array = PacketsArray::<()>::new();
array.buffer_end = CRYPTO_PACKET_BUFFER_SIZE;
assert!(array.push_back(()).is_err());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, CRYPTO_PACKET_BUFFER_SIZE);
}
#[test]
fn pop_front_some() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert!(array.pop_front().is_some());
assert_eq!(array.buffer_start, 1);
assert_eq!(array.buffer_end, 1);
assert!(array.get(0).is_none());
}
#[test]
fn pop_front_none() {
let mut array = PacketsArray::<()>::new();
array.buffer_end = 1;
assert!(array.pop_front().is_none());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 1);
}
#[test]
fn pop_front_empty() {
let mut array = PacketsArray::<()>::new();
assert!(array.pop_front().is_none());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 0);
}
#[test]
fn get() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert!(array.get(0).is_some());
assert!(array.get(1).is_none());
assert!(array.get(2).is_none());
}
#[test]
fn get_mut() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert!(array.get_mut(0).is_some());
assert!(array.get_mut(1).is_none());
assert!(array.get_mut(2).is_none());
}
#[test]
fn remove() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert!(array.remove(0).is_some());
assert!(array.remove(0).is_none());
assert!(array.remove(1).is_none());
assert!(array.remove(2).is_none());
assert!(array.get(0).is_none());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 1);
}
#[test]
fn set_buffer_end() {
let mut array = PacketsArray::<()>::new();
assert!(array.set_buffer_end(7).is_ok());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 7);
assert!(array.set_buffer_end(CRYPTO_PACKET_BUFFER_SIZE).is_ok());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, CRYPTO_PACKET_BUFFER_SIZE);
}
#[test]
fn set_buffer_end_too_big_index() {
let mut array = PacketsArray::<()>::new();
assert!(array.set_buffer_end(CRYPTO_PACKET_BUFFER_SIZE + 1).is_err());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 0);
}
#[test]
fn set_buffer_end_lower_than_end_index() {
let mut array = PacketsArray::<()>::new();
array.buffer_end = 7;
assert!(array.set_buffer_end(6).is_err());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 7);
}
#[test]
fn set_buffer_start() {
let mut array = PacketsArray::<()>::new();
assert!(array.push_back(()).is_ok());
assert!(array.push_back(()).is_ok());
assert!(array.set_buffer_start(1).is_ok());
assert!(array.set_buffer_start(1).is_ok());
assert!(array.get(0).is_none());
assert!(array.get(1).is_some());
assert_eq!(array.buffer_start, 1);
assert_eq!(array.buffer_end, 2);
assert!(array.set_buffer_start(2).is_ok());
assert!(array.set_buffer_start(2).is_ok());
assert!(array.get(0).is_none());
assert!(array.get(1).is_none());
assert_eq!(array.buffer_start, 2);
assert_eq!(array.buffer_end, 2);
}
#[test]
fn set_buffer_start_too_big_index() {
let mut array = PacketsArray::<()>::new();
assert!(array.set_buffer_start(1).is_err());
assert_eq!(array.buffer_start, 0);
assert_eq!(array.buffer_end, 0);
}
#[test]
fn set_buffer_start_lower_than_start_index() {
let mut array = PacketsArray::<()>::new();
array.buffer_start = 7;
array.buffer_end = 7;
assert!(array.set_buffer_start(1).is_err());
assert_eq!(array.buffer_start, 7);
assert_eq!(array.buffer_end, 7);
}
}