use liballoc::string::String;
use sync::mpsc::Sender;
use core::{ptr, cmp};
use liballoc::raw_vec::RawVec;
#[derive(Debug)]
pub struct Error {
pub msg: String
}
pub trait Read {
fn read(&mut self, dest: &mut [u8]) -> Result<usize, String>;
}
pub trait Receive {
fn on_recv(&mut self, s: Sender<()>);
}
pub trait Write {
fn write(&mut self, dest: &[u8]) -> Result<usize, String>;
}
pub enum SeekFrom {
Start(u64),
End(u64),
Current(i64)
}
pub trait Seek {
fn size(&self) -> u64;
fn seek(&mut self, pos: SeekFrom) -> Result<u64, String>;
}
pub trait Connect {
fn connect() -> Result<(), String>;
fn disconnect() -> Result<(), String>;
}
pub struct Fifo<T> {
v: RawVec<T>, cap: usize, w: usize, r: Option<usize> }
impl<T> Fifo<T> {
pub fn new(capacity: usize) -> Fifo<T> {
let cap = cmp::max(1, capacity);
Fifo { v: RawVec::with_capacity(cap), cap: cap, w: 0, r: None }
}
pub fn push_front(&mut self, item: T) -> Result<(), T> {
if let Some(r) = self.r {
if self.w == r {
return Err(item)
}
}
unsafe { ptr::write(self.v.ptr().offset(self.w as isize), item); }
if let None = self.r {
self.r = Some(self.w);
}
self.w += 1;
if self.w == self.cap {
self.w = 0;
}
Ok(())
}
pub fn pop_back(&mut self) -> Option<T> {
let mut r = match self.r {
None => return None,
Some(r) => r
};
let item = unsafe { ptr::read(self.v.ptr().offset(r as isize)) };
r += 1;
if r == self.w {
self.r = None;
} else {
if r == self.cap {
r = 0;
}
self.r = Some(r);
}
Some(item)
}
}
#[cfg(test)]
mod test {
use super::Fifo;
fn helper_setup_offset() -> Fifo<u32> {
let mut v: Fifo<u32> = Fifo::new(10);
for i in 0..5 {
assert_eq!(v.push_front(i), Ok(()));
}
for i in 0..5 {
assert_eq!(v.pop_back().unwrap(), i);
}
v
}
#[test]
fn fifo_basic_ops() {
let mut v: Fifo<u32> = Fifo::new(10);
for i in 0..5 {
assert_eq!(v.push_front(i), Ok(()));
}
for i in 0..5 {
assert_eq!(v.pop_back().unwrap(), i);
}
}
#[test]
fn fifo_wrapping() {
let mut v = helper_setup_offset();
for i in 0..10 {
assert_eq!(v.push_front(i), Ok(()));
}
for i in 0..10 {
assert_eq!(v.pop_back().unwrap(), i);
}
}
#[test]
fn fifo_overrun() {
let mut v = helper_setup_offset();
for i in 0..10 {
assert_eq!(v.push_front(i), Ok(()));
}
assert_eq!(v.push_front(11), Err(11));
}
#[test]
fn fifo_underrun() {
let mut v = helper_setup_offset();
assert_eq!(v.push_front(42), Ok(()));
assert_eq!(v.pop_back().unwrap(), 42);
assert_eq!(v.pop_back(), None);
}
}