avr-oxide 0.4.1

An extremely simple Rusty operating system for AVR microcontrollers
/* 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 =====================================================================