1
Fork 0

Added default Cargo feature "use_std", no_std without it.

`cargo test` still passes.

`cargo build --no-default-features` builds, but no further tests done.
This commit is contained in:
Alex Helfet 2017-12-21 05:08:54 +00:00
parent 40366a6afe
commit 78ef89a4ba
3 changed files with 77 additions and 25 deletions

View file

@ -14,8 +14,15 @@ cobs = "^0.1.2"
error-chain = "^0.11.0"
ref_slice = "^1.1.1"
[dependencies.core-io]
git = "https://github.com/QuiltOS/core-io"
rev = "f084f913011c9916d420b520ead3953a2ccb950e"
[features]
default_features = []
default = ["use_std"]
# Enable to print all data to stdout for testing.
trace = []
# Use standard library, enabled by default; disable for no_std.
use_std = []

View file

@ -1,20 +1,37 @@
//! Representations of errors returned by this crate.
#[cfg(feature = "use_std")]
use std::io;
error_chain! {
foreign_links {
Io(io::Error);
}
#[cfg(feature = "use_std")]
use std::result;
#[cfg(not(feature = "use_std"))]
use core::result;
errors {
CobsDecodeFailed {
description("COBS decode failed"),
display("COBS decode failed"),
}
EofDuringFrame {
description("end of file during a frame"),
display("end of file during a frame"),
}
pub type Result<T> = result::Result<T, Error>;
#[cfg_attr(feature = "use_std", derive(Debug))]
pub enum Error {
/// COBS decode failed
CobsDecodeFailed,
/// End of file while reading a frame
EofDuringFrame,
/// Forwarded io::Error.
#[cfg(feature = "use_std")]
Io(io::Error),
/// Forwarded Io error.
///
/// TODO: Store some extra value here.
#[cfg(not(feature = "use_std"))]
Io,
}
#[cfg(feature = "use_std")]
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error::Io(e)
}
}

View file

@ -16,27 +16,40 @@
//! ## Cargo feature flags
//! `trace`: Enable to print all data to stdout for testing.
//!
//! `use_std`: Use standard library, enabled by default; disable for no_std.
//!
//! ## TODO
//! * Start frame with a zero as well, then we detect partial frames.
//! * Add a length field to the beginning of the frame and a
//! checksum to the end. Perhaps make them optional.
//! * Support no_std.
#![deny(warnings)]
#![feature(conservative_impl_trait)]
#![cfg_attr(not(feature = "use_std"), no_std)]
extern crate cobs;
#[macro_use]
extern crate error_chain;
#[cfg(not(feature = "use_std"))]
extern crate core_io;
extern crate ref_slice;
#[cfg(feature = "use_std")]
pub mod channel;
pub mod error;
use error::{Error, ErrorKind, Result};
#[allow(unused_imports)]
use error::{Error, Result};
#[cfg(feature = "use_std")]
use ref_slice::ref_slice_mut;
#[cfg(feature = "use_std")]
use std::io::{self, Read, Write};
#[cfg(not(feature = "use_std"))]
use core_io::{Read, Write};
const FRAME_END: u8 = 0;
/// Sends frames over an underlying `io::Write` instance.
@ -57,13 +70,27 @@ impl<W: Write> Sender<W> {
#[cfg(feature = "trace")] {
println!("framed: Sending code = {:?}", code);
}
self.w.write(&code)?;
#[cfg(feature = "use_std")] {
self.w.write(&code)?;
}
#[cfg(not(feature = "use_std"))] {
self.w.write(&code)
.map_err(|_| Error::Io)?;
}
Ok(())
}
}
/// Receives frames from an underlying `io::Read` instance.
///
/// TODO: Add a recv() variant suitable for no_std use, e.g. one that
/// takes a `&mut [u8]`.
pub struct Receiver<R: Read> {
#[cfg_attr(not(feature = "use_std"), allow(dead_code))]
/// The underlying reader
r: R,
}
@ -75,6 +102,7 @@ impl<R: Read> Receiver<R> {
}
}
#[cfg(feature = "use_std")]
pub fn recv(&mut self) -> Result<Vec<u8>> {
let mut next_frame = Vec::new();
@ -86,9 +114,9 @@ impl<R: Read> Receiver<R> {
}
match res {
Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof =>
return Err(Error::from(ErrorKind::EofDuringFrame)),
return Err(Error::EofDuringFrame),
Ok(0) =>
return Err(Error::from(ErrorKind::EofDuringFrame)),
return Err(Error::EofDuringFrame),
Err(e) => return Err(Error::from(e)),
Ok(_) => (),
};
@ -105,14 +133,14 @@ impl<R: Read> Receiver<R> {
assert!(b == FRAME_END);
cobs::decode_vec(&next_frame)
.map_err(|_| Error::from(ErrorKind::CobsDecodeFailed))
.map_err(|_| Error::CobsDecodeFailed)
}
}
#[cfg(test)]
mod tests {
use channel::Channel;
use error::{Error, ErrorKind};
use error::Error;
use std::io::{Read, Write};
use super::{Receiver, Sender};
@ -165,7 +193,7 @@ mod tests {
fn empty_input() {
let (mut _tx, mut rx) = pair();
match rx.recv() {
Err(Error(ErrorKind::EofDuringFrame, _)) => (),
Err(Error::EofDuringFrame) => (),
e @ _ => panic!("Bad value: {:?}", e)
}
}