From 67d7226d70c2e67a3149b82eca4cdf239e3b2dc3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 21 Apr 2019 22:08:42 +0200 Subject: [PATCH 1/4] v0.1.2 --- CHANGELOG.md | 12 +++++++++++- Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d558354..81e2f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v0.1.2] - 2019-04-21 + +### Added + +- `Error` gained a `map` method that lets you transform the error in the + `Error::Other` variant into a different type. + +- `Error` now implements the `From` trait. + ## [v0.1.1] - 2018-01-10 ### Fixed @@ -17,5 +26,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Initial release -[Unreleased]: https://github.com/japaric/nb/compare/v0.1.1...HEAD +[Unreleased]: https://github.com/japaric/nb/compare/v0.1.2...HEAD +[v0.1.2]: https://github.com/japaric/nb/compare/v0.1.1...v0.1.2 [v0.1.1]: https://github.com/japaric/nb/compare/v0.1.0...v0.1.1 diff --git a/Cargo.toml b/Cargo.toml index 7aad001..7f06838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["await", "futures", "IO"] license = "MIT OR Apache-2.0" name = "nb" repository = "https://github.com/japaric/nb" -version = "0.1.1" +version = "0.1.2" [features] unstable = [] From 1869ae8740c4d5b57ffea7525c38f0f11ced71ca Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Fri, 3 Jul 2020 08:49:04 +0200 Subject: [PATCH 2/4] Remove unstable feature and code --- .github/workflows/ci.yml | 8 +- .github/workflows/clippy.yml | 4 + CHANGELOG.md | 7 + Cargo.toml | 6 - src/lib.rs | 281 ++--------------------------------- 5 files changed, 32 insertions(+), 274 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7665c24..5a8e9de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: name: Continuous integration +env: + RUSTFLAGS: '-D warnings' + jobs: ci-linux: runs-on: ubuntu-latest @@ -37,9 +40,8 @@ jobs: - uses: actions-rs/cargo@v1 with: command: check - args: --target=${{ matrix.TARGET }} --features unstable + args: --target=${{ matrix.TARGET }} - uses: actions-rs/cargo@v1 - if: ${{ matrix.rust == 'nightly' }} with: command: test - args: --target=${{ matrix.TARGET }} --features unstable + args: --target=${{ matrix.TARGET }} diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index adc3a6e..d67f81a 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -4,6 +4,10 @@ on: pull_request: name: Clippy check + +env: + RUSTFLAGS: '-D warnings' + jobs: clippy_check: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index d558354..ecc2933 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v1.0.0] + +### Changed + +- [breaking-change] The `unstable` feature and its code has been removed. + This includes the macros `try_nb!` and `await!`. + ## [v0.1.1] - 2018-01-10 ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 4164ef4..1eee647 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,3 @@ homepage = "https://github.com/rust-embedded/nb" documentation = "https://docs.rs/nb" readme = "README.md" version = "0.1.1" - -[features] -unstable = [] - -[dev-dependencies] -futures = "0.1.17" diff --git a/src/lib.rs b/src/lib.rs index 3bc561d..67823f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,29 +57,25 @@ //! } //! ``` //! -//! You can use the *never type* (`!`) to signal that some API has no fatal +//! You can use `Infallible` to signal that some API has no fatal //! errors but may block: //! //! ``` -//! #![feature(never_type)] +//! # extern crate core; +//! use core::convert::Infallible; //! //! // This returns `Ok(())` or `Err(nb::Error::WouldBlock)` -//! fn maybe_blocking_api() -> nb::Result<(), !> { +//! fn maybe_blocking_api() -> nb::Result<(), Infallible> { //! // .. //! # Ok(()) //! } //! ``` //! -//! Once your API uses [`nb::Result`](type.Result.html) you can leverage the -//! [`block!`], [`try_nb!`] and [`await!`] macros to adapt it for blocking -//! operation, or for non-blocking operation with `futures` or `await`. -//! -//! **NOTE** Currently, both `try_nb!` and `await!` are feature gated behind the `unstable` Cargo -//! feature. +//! Once your API uses [`nb::Result`] you can leverage the [`block!`], macro +//! to adapt it for blocking operation, or handle scheduling yourself. //! //! [`block!`]: macro.block.html -//! [`try_nb!`]: macro.try_nb.html -//! [`await!`]: macro.await.html +//! [`nb::Result`]: type.Result.html //! //! # Examples //! @@ -92,11 +88,9 @@ //! as global singletons and that no preemption is possible (i.e. interrupts are disabled).* //! //! ``` -//! #![feature(never_type)] -//! +//! # extern crate core; +//! # use core::convert::Infallible; //! // This is the `hal` crate -//! // Note that it doesn't depend on the `futures` crate -//! //! extern crate nb; //! //! /// An LED @@ -137,8 +131,8 @@ //! //! impl Timer { //! /// Waits until the timer times out -//! pub fn wait(&self) -> nb::Result<(), !> { -//! //^ NOTE the `!` indicates that this operation can block but has no +//! pub fn wait(&self) -> nb::Result<(), Infallible> { +//! //^ NOTE the `Infallible` indicates that this operation can block but has no //! // other form of error //! //! // .. @@ -152,7 +146,8 @@ //! Turn on an LED for one second and *then* loops back serial data. //! //! ``` -//! # #![feature(never_type)] +//! # extern crate core; +//! # use core::convert::Infallible; //! #[macro_use(block)] //! extern crate nb; //! @@ -161,7 +156,7 @@ //! fn main() { //! // Turn the LED on for one second //! Led.on(); -//! block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = ! +//! block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = Infallible //! Led.off(); //! //! // Serial interface loopback @@ -174,6 +169,7 @@ //! //! # mod hal { //! # use nb; +//! # use Infallible; //! # pub struct Led; //! # impl Led { //! # pub fn off(&self) {} @@ -186,180 +182,12 @@ //! # } //! # pub struct Timer; //! # impl Timer { -//! # pub fn wait(&self) -> nb::Result<(), !> { Ok(()) } -//! # } -//! # } -//! ``` -//! -//! ## `futures` -//! -//! Blinks an LED every second *and* loops back serial data. Both tasks run -//! concurrently. -//! -//! ``` -//! #![feature(conservative_impl_trait)] -//! #![feature(never_type)] -//! -//! extern crate futures; -//! #[macro_use(try_nb)] -//! extern crate nb; -//! -//! use futures::{Async, Future}; -//! use futures::future::{self, Loop}; -//! use hal::{Error, Led, Serial, Timer}; -//! -//! /// `futures` version of `Timer.wait` -//! /// -//! /// This returns a future that must be polled to completion -//! fn wait() -> impl Future { -//! future::poll_fn(|| { -//! Ok(Async::Ready(try_nb!(Timer.wait()))) -//! }) -//! } -//! -//! /// `futures` version of `Serial.read` -//! /// -//! /// This returns a future that must be polled to completion -//! fn read() -> impl Future { -//! future::poll_fn(|| { -//! Ok(Async::Ready(try_nb!(Serial.read()))) -//! }) -//! } -//! -//! /// `futures` version of `Serial.write` -//! /// -//! /// This returns a future that must be polled to completion -//! fn write(byte: u8) -> impl Future { -//! future::poll_fn(move || { -//! Ok(Async::Ready(try_nb!(Serial.write(byte)))) -//! }) -//! } -//! -//! fn main() { -//! // Tasks -//! let mut blinky = future::loop_fn::<_, (), _, _>(true, |state| { -//! wait().map(move |_| { -//! if state { -//! Led.on(); -//! } else { -//! Led.off(); -//! } -//! -//! Loop::Continue(!state) -//! }) -//! }); -//! -//! let mut loopback = future::loop_fn::<_, (), _, _>((), |_| { -//! read().and_then(|byte| { -//! write(byte) -//! }).map(|_| { -//! Loop::Continue(()) -//! }) -//! }); -//! -//! // Event loop -//! loop { -//! blinky.poll().unwrap(); // NOTE(unwrap) E = ! -//! loopback.poll().unwrap(); -//! # break -//! } -//! } -//! -//! # mod hal { -//! # use nb; -//! # pub struct Led; -//! # impl Led { -//! # pub fn off(&self) {panic!()} -//! # pub fn on(&self) {} -//! # } -//! # #[derive(Debug)] -//! # pub enum Error {} -//! # pub struct Serial; -//! # impl Serial { -//! # pub fn read(&self) -> nb::Result { Err(nb::Error::WouldBlock) } -//! # pub fn write(&self, _: u8) -> nb::Result<(), Error> { Err(nb::Error::WouldBlock) } -//! # } -//! # pub struct Timer; -//! # impl Timer { -//! # pub fn wait(&self) -> nb::Result<(), !> { Err(nb::Error::WouldBlock) } -//! # } -//! # } -//! ``` -//! -//! ## `await!` -//! -//! This is equivalent to the `futures` example but with much less boilerplate. -//! -//! ``` -//! #![feature(generator_trait)] -//! #![feature(generators)] -//! #![feature(never_type)] -//! -//! #[macro_use(await)] -//! extern crate nb; -//! -//! extern crate core; -//! use core::ops::Generator; -//! use core::pin::Pin; -//! -//! use hal::{Led, Serial, Timer}; -//! -//! fn main() { -//! // Tasks -//! let mut blinky = || { -//! let mut state = false; -//! loop { -//! // `await!` means suspend / yield instead of blocking -//! await!(Timer.wait()).unwrap(); // NOTE(unwrap) E = ! -//! -//! state = !state; -//! -//! if state { -//! Led.on(); -//! } else { -//! Led.off(); -//! } -//! } -//! }; -//! -//! let mut loopback = || { -//! loop { -//! let byte = await!(Serial.read()).unwrap(); -//! await!(Serial.write(byte)).unwrap(); -//! } -//! }; -//! -//! let blinky = Pin::new(&mut blinky); -//! let loopback = Pin::new(&mut loopback); -//! // Event loop -//! loop { -//! blinky.resume(()); -//! loopback.resume(()); -//! # break -//! } -//! } -//! -//! # mod hal { -//! # use nb; -//! # pub struct Led; -//! # impl Led { -//! # pub fn off(&self) {} -//! # pub fn on(&self) {} -//! # } -//! # pub struct Serial; -//! # impl Serial { -//! # pub fn read(&self) -> nb::Result { Err(nb::Error::WouldBlock) } -//! # pub fn write(&self, _: u8) -> nb::Result<(), ()> { Err(nb::Error::WouldBlock) } -//! # } -//! # pub struct Timer; -//! # impl Timer { -//! # pub fn wait(&self) -> nb::Result<(), !> { Err(nb::Error::WouldBlock) } +//! # pub fn wait(&self) -> nb::Result<(), Infallible> { Ok(()) } //! # } //! # } //! ``` #![no_std] -#![deny(warnings)] use core::fmt; @@ -410,46 +238,6 @@ impl From for Error { } } -/// Await operation (*won't work until the language gains support for -/// generators*) -/// -/// This macro evaluates the expression `$e` *cooperatively* yielding control -/// back to the (generator) caller whenever `$e` evaluates to -/// `Error::WouldBlock`. -/// -/// # Requirements -/// -/// This macro must be called within a generator body. -/// -/// # Input -/// -/// An expression `$e` that evaluates to `nb::Result` -/// -/// # Output -/// -/// - `Ok(t)` if `$e` evaluates to `Ok(t)` -/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))` -#[cfg(feature = "unstable")] -#[macro_export] -macro_rules! await { - ($e:expr) => { - loop { - #[allow(unreachable_patterns)] - match $e { - Err($crate::Error::Other(e)) => - { - #[allow(unreachable_code)] - break Err(e) - } - Err($crate::Error::WouldBlock) => {} // yield (see below) - Ok(x) => break Ok(x), - } - - yield - } - }; -} - /// Turns the non-blocking expression `$e` into a blocking operation. /// /// This is accomplished by continuously calling the expression `$e` until it no @@ -480,40 +268,3 @@ macro_rules! block { } }; } - -/// Future adapter -/// -/// This is a *try* operation from a `nb::Result` to a `futures::Poll` -/// -/// # Requirements -/// -/// This macro must be called within a function / closure that has signature -/// `fn(..) -> futures::Poll`. -/// -/// This macro requires that the [`futures`] crate is in the root of the crate. -/// -/// [`futures`]: https://crates.io/crates/futures -/// -/// # Input -/// -/// An expression `$e` that evaluates to `nb::Result` -/// -/// # Early return -/// -/// - `Ok(Async::NotReady)` if `$e` evaluates to `Err(nb::Error::WouldBlock)` -/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))` -/// -/// # Output -/// -/// `t` if `$e` evaluates to `Ok(t)` -#[cfg(feature = "unstable")] -#[macro_export] -macro_rules! try_nb { - ($e:expr) => { - match $e { - Err($crate::Error::Other(e)) => return Err(e), - Err($crate::Error::WouldBlock) => return Ok(::futures::Async::NotReady), - Ok(x) => x, - } - }; -} From d7ff88a46561e56aa378b36f102051eb567f8932 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Fri, 3 Jul 2020 08:50:03 +0200 Subject: [PATCH 3/4] Use Rust edition 2018 --- Cargo.toml | 1 + src/lib.rs | 33 +++++++++++++-------------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1eee647..0b75084 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ homepage = "https://github.com/rust-embedded/nb" documentation = "https://docs.rs/nb" readme = "README.md" version = "0.1.1" +edition = "2018" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 67823f6..359f61a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,6 @@ //! errors but may block: //! //! ``` -//! # extern crate core; //! use core::convert::Infallible; //! //! // This returns `Ok(())` or `Err(nb::Error::WouldBlock)` @@ -88,10 +87,9 @@ //! as global singletons and that no preemption is possible (i.e. interrupts are disabled).* //! //! ``` -//! # extern crate core; //! # use core::convert::Infallible; //! // This is the `hal` crate -//! extern crate nb; +//! use nb; //! //! /// An LED //! pub struct Led; @@ -146,30 +144,25 @@ //! Turn on an LED for one second and *then* loops back serial data. //! //! ``` -//! # extern crate core; -//! # use core::convert::Infallible; -//! #[macro_use(block)] -//! extern crate nb; +//! use nb::block; //! //! use hal::{Led, Serial, Timer}; //! -//! fn main() { -//! // Turn the LED on for one second -//! Led.on(); -//! block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = Infallible -//! Led.off(); -//! -//! // Serial interface loopback -//! # return; -//! loop { -//! let byte = block!(Serial.read()).unwrap(); -//! block!(Serial.write(byte)).unwrap(); -//! } +//! // Turn the LED on for one second +//! Led.on(); +//! block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = Infallible +//! Led.off(); +//! +//! // Serial interface loopback +//! # return; +//! loop { +//! let byte = block!(Serial.read()).unwrap(); +//! block!(Serial.write(byte)).unwrap(); //! } //! //! # mod hal { //! # use nb; -//! # use Infallible; +//! # use core::convert::Infallible; //! # pub struct Led; //! # impl Led { //! # pub fn off(&self) {} From 4cb937c6935ba60f793424b3c3214d9d0c3f855a Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Fri, 3 Jul 2020 14:05:59 +0200 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 859ac1d..d0201b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [v1.0.0] - ### Changed - [breaking-change] The `unstable` feature and its code has been removed. @@ -33,6 +31,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Initial release -[Unreleased]: https://github.com/japaric/nb/compare/v0.1.2...HEAD -[v0.1.2]: https://github.com/japaric/nb/compare/v0.1.1...v0.1.2 -[v0.1.1]: https://github.com/japaric/nb/compare/v0.1.0...v0.1.1 +[Unreleased]: https://github.com/rust-embedded/nb/compare/v0.1.2...HEAD +[v0.1.2]: https://github.com/rust-embedded/nb/compare/v0.1.1...v0.1.2 +[v0.1.1]: https://github.com/rust-embedded/nb/compare/v0.1.0...v0.1.1