use core::fmt;
use core::result;
pub fn blocking<F, O, E>(non_blocking: F) -> result::Result<O, E>
where F: Fn() -> result::Result<O, E>,
E: Into<Error> + Clone {
loop {
match non_blocking() {
Err(x) => {
if x.clone().into() != Error::BufferExhausted {
return Err(x);
}
},
Ok(x) => {
return Ok(x);
},
}
}
}
pub type Result<T> = result::Result<T, Error>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
BufferExhausted,
InvalidInput,
ErrorDetectionCode,
Other,
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
let mut bytes_written = 0;
while bytes_written < buf.len() {
match self.write(&buf[bytes_written..]) {
Ok(n) => bytes_written += n,
Err(Error::BufferExhausted) => (),
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_str(&mut self, s: &str) -> Result<()> {
self.write_all(s.as_bytes())
}
#[allow(unused_must_use)]
fn write_fmt(&mut self, args: fmt::Arguments) -> Result<()> {
struct Adapter<'a, T>
where T: ?Sized + 'a {
inner: &'a mut T,
error: Option<Error>,
};
impl<'a, T> fmt::Write for Adapter<'a, T>
where T: Write + ?Sized {
fn write_str(&mut self, s: &str) -> result::Result<(), fmt::Error> {
match Write::write_str(self.inner, s) {
Ok(()) => Ok(()),
Err(e) => {
self.error = Some(e);
Err(fmt::Error)
},
}
}
}
let mut adapter = Adapter{
inner: self,
error: None,
};
fmt::Write::write_fmt(&mut adapter, args);
match adapter.error {
Some(e) => Err(e),
None => Ok(()),
}
}
}
pub trait Read {
fn read_until(&mut self, byte: u8, buf: &mut [u8]) -> Result<usize>;
}
#[cfg(test)]
mod tests {
use io::*;
#[test]
fn write_test() {
struct TestBuffer {
buffer: [u8; 100],
index: usize,
}
impl Write for TestBuffer {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.buffer[self.index..self.index+buf.len()].clone_from_slice(buf);
self.index += buf.len();
Ok(buf.len())
}
}
let mut test_buffer = TestBuffer{buffer: [0u8; 100], index: 0};
write!(test_buffer, "This {} a {}", "is", "test").unwrap();
assert_eq!(test_buffer.buffer[..test_buffer.index].len(), "This is a test".as_bytes().len());
assert_eq!(&test_buffer.buffer[..test_buffer.index], "This is a test".as_bytes());
}
}