1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
/* mod.rs
*
* Developed by Tim Walls <tim.walls@snowgoons.com>
* Copyright (c) All Rights Reserved, Tim Walls
*/
//! Simple IO traits (a very, very, very cutdown version of std::io). In due
//! course hopefully somewhat /less/ cutdown, and maybe even derived from
//! std::io in the style of the `core_io` crate, but right now this is what
//! we've got.
//!
//! (We can't use `core_io` at the moment because the build scripts do not
//! recognise our custom toolchain; if we ever get to a place where the
//! regular Rust toolchain works on AVR again, we may be able to revisit this.)
// Imports ===================================================================
use avr_oxide::OxideResult::{Ok};
// Declarations ==============================================================
/// Errors that can result from our IO routines
#[cfg_attr(not(target_arch="avr"), derive(Debug))]
#[cfg_attr(target_arch="avr", derive(ufmt::derive::uDebug))]
pub enum IoError {
/// We have reached the end of a file for reading
EndOfFile,
/// We have no remaining free space for writing
NoFreeSpace,
/// Generic IO error
Unknown,
/// Write not allowed (read-only device)
WriteProhibited,
/// Read not allowed (write-only device)
ReadProhibited,
/// The device is not ready (or formatted)
DeviceNotReady,
/// The requested read/write was out of range
OutOfRange,
/// The requested resource already exists
Exists,
/// The requested resource does not exist
NotFound,
/// There was a mismatch between endianess representations (e.g. a
/// big-endian formatted device was read on a little-endian processor)
EndianMismatch,
/// The underlying filesystem (or whatever) has not been formatted
Unformatted,
/// Bad or conflicting options were passed to an IO call
BadOptions
}
pub type Result<T> = avr_oxide::OxideResult<T,IoError>;
pub trait Read {
fn read(&mut self, _buf: &mut [u8]) -> avr_oxide::io::Result<usize>;
fn read_exact(&mut self, buf: &mut [u8]) -> avr_oxide::io::Result<()> {
let mut offset = 0usize;
while offset < buf.len() {
let bytes_read = self.read(&mut buf[offset..])?;
offset += bytes_read;
}
Ok(())
}
}
pub trait Write {
fn flush(&mut self) -> avr_oxide::io::Result<()>;
fn write_buffered(&mut self, buf:&[u8]) -> avr_oxide::io::Result<usize>;
fn write(&mut self, buf: &[u8]) -> avr_oxide::io::Result<usize> {
let bytes = self.write_buffered(buf)?;
self.flush()?;
Ok(bytes)
}
fn write_all(&mut self, buf: &[u8]) -> avr_oxide::io::Result<()> {
let mut offset = 0usize;
while offset < buf.len() {
let bytes_written = self.write_buffered(&buf[offset..])?;
offset += bytes_written;
}
self.flush()?;
Ok(())
}
}
// Code ======================================================================
#[cfg(not(target_arch="avr"))]
impl Read for std::io::Stdin {
fn read(&mut self, buf: &mut [u8]) -> avr_oxide::io::Result<usize> {
match std::io::Read::read(self, buf) {
std::result::Result::Ok(b) => avr_oxide::OxideResult::Ok(b),
std::result::Result::Err(_e) => avr_oxide::OxideResult::Err(IoError::Unknown)
}
}
}
#[cfg(not(target_arch="avr"))]
impl Write for std::io::Stdout {
fn write_buffered(&mut self, buf: &[u8]) -> avr_oxide::io::Result<usize> {
match std::io::Write::write(self, buf) {
std::result::Result::Ok(b) => avr_oxide::OxideResult::Ok(b),
std::result::Result::Err(_e) => avr_oxide::OxideResult::Err(IoError::Unknown)
}
}
fn flush(&mut self) -> Result<()> {
std::io::Write::flush(self);
avr_oxide::OxideResult::Ok(())
}
}
#[cfg(not(target_arch="avr"))]
impl Write for std::io::Stderr {
fn write_buffered(&mut self, buf: &[u8]) -> Result<usize> {
match std::io::Write::write(self, buf) {
std::result::Result::Ok(b) => avr_oxide::OxideResult::Ok(b),
std::result::Result::Err(_e) => avr_oxide::OxideResult::Err(IoError::Unknown)
}
}
fn flush(&mut self) -> Result<()> {
std::io::Write::flush(self);
avr_oxide::OxideResult::Ok(())
}
}
// Tests =====================================================================