1//! Minimal and reusable non-blocking I/O layer
2//!
3//! The ultimate goal of this crate is *code reuse*. With this crate you can
4//! write *core* I/O APIs that can then be adapted to operate in either blocking
5//! or non-blocking manner. Furthermore those APIs are not tied to a particular
6//! asynchronous model and can be adapted to work with the `futures` model or
7//! with the `async` / `await` model.
8//!
9//! # Core idea
10//!
11//! The [`WouldBlock`](enum.Error.html) error variant signals that the operation
12//! can't be completed *right now* and would need to block to complete.
13//! [`WouldBlock`](enum.Error.html) is a special error in the sense that's not
14//! *fatal*; the operation can still be completed by retrying again later.
15//!
16//! [`nb::Result`](type.Result.html) is based on the API of
17//! [`std::io::Result`](https://doc.rust-lang.org/std/io/type.Result.html),
18//! which has a `WouldBlock` variant in its
19//! [`ErrorKind`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html).
20//!
21//! We can map [`WouldBlock`](enum.Error.html) to different blocking and
22//! non-blocking models:
23//!
24//! - In blocking mode: [`WouldBlock`](enum.Error.html) means try again right
25//! now (i.e. busy wait)
26//! - In `futures` mode: [`WouldBlock`](enum.Error.html) means
27//! [`Async::NotReady`](https://docs.rs/futures)
28//! - In `await` mode: [`WouldBlock`](enum.Error.html) means `yield`
29//! (suspend the generator)
30//!
31//! # How to use this crate
32//!
33//! Application specific errors can be put inside the `Other` variant in the
34//! [`nb::Error`](enum.Error.html) enum.
35//!
36//! So in your API instead of returning `Result<T, MyError>` return
37//! `nb::Result<T, MyError>`
38//!
39//! ```
40//! enum MyError {
41//! ThisError,
42//! ThatError,
43//! // ..
44//! }
45//!
46//! // This is a blocking function, so it returns a normal `Result`
47//! fn before() -> Result<(), MyError> {
48//! // ..
49//! # Ok(())
50//! }
51//!
52//! // This is now a potentially (read: *non*) blocking function so it returns `nb::Result`
53//! // instead of blocking
54//! fn after() -> nb::Result<(), MyError> {
55//! // ..
56//! # Ok(())
57//! }
58//! ```
59//!
60//! You can use the *never type* (`!`) to signal that some API has no fatal
61//! errors but may block:
62//!
63//! ```
64//! #![feature(never_type)]
65//!
66//! // This returns `Ok(())` or `Err(nb::Error::WouldBlock)`
67//! fn maybe_blocking_api() -> nb::Result<(), !> {
68//! // ..
69//! # Ok(())
70//! }
71//! ```
72//!
73//! Once your API uses [`nb::Result`](type.Result.html) you can leverage the
74//! [`block!`], [`try_nb!`] and [`await!`] macros to adapt it for blocking
75//! operation, or for non-blocking operation with `futures` or `await`.
76//!
77//! **NOTE** Currently, both `try_nb!` and `await!` are feature gated behind the `unstable` Cargo
78//! feature.
79//!
80//! [`block!`]: macro.block.html
81//! [`try_nb!`]: macro.try_nb.html
82//! [`await!`]: macro.await.html
83//!
84//! # Examples
85//!
86//! ## A Core I/O API
87//!
88//! Imagine the code (crate) below represents a Hardware Abstraction Layer for some microcontroller
89//! (or microcontroller family).
90//!
91//! *In this and the following examples let's assume for simplicity that peripherals are treated
92//! as global singletons and that no preemption is possible (i.e. interrupts are disabled).*
93//!
94//! ```
95//! #![feature(never_type)]
96//!
97//! // This is the `hal` crate
98//! // Note that it doesn't depend on the `futures` crate
99//!
100//! extern crate nb;
101//!
102//! /// An LED
103//! pub struct Led;
104//!
105//! impl Led {
106//! pub fn off(&self) {
107//! // ..
108//! }
109//! pub fn on(&self) {
110//! // ..
111//! }
112//! }
113//!
114//! /// Serial interface
115//! pub struct Serial;
116//! pub enum Error {
117//! Overrun,
118//! // ..
119//! }
120//!
121//! impl Serial {
122//! /// Reads a single byte from the serial interface
123//! pub fn read(&self) -> nb::Result<u8, Error> {
124//! // ..
125//! # Ok(0)
126//! }
127//!
128//! /// Writes a single byte to the serial interface
129//! pub fn write(&self, byte: u8) -> nb::Result<(), Error> {
130//! // ..
131//! # Ok(())
132//! }
133//! }
134//!
135//! /// A timer used for timeouts
136//! pub struct Timer;
137//!
138//! impl Timer {
139//! /// Waits until the timer times out
140//! pub fn wait(&self) -> nb::Result<(), !> {
141//! //^ NOTE the `!` indicates that this operation can block but has no
142//! // other form of error
143//!
144//! // ..
145//! # Ok(())
146//! }
147//! }
148//! ```
149//!
150//! ## Blocking mode
151//!
152//! Turn on an LED for one second and *then* loops back serial data.
153//!
154//! ```
155//! # #![feature(never_type)]
156//! #[macro_use(block)]
157//! extern crate nb;
158//!
159//! use hal::{Led, Serial, Timer};
160//!
161//! fn main() {
162//! // Turn the LED on for one second
163//! Led.on();
164//! block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = !
165//! Led.off();
166//!
167//! // Serial interface loopback
168//! # return;
169//! loop {
170//! let byte = block!(Serial.read()).unwrap();
171//! block!(Serial.write(byte)).unwrap();
172//! }
173//! }
174//!
175//! # mod hal {
176//! # use nb;
177//! # pub struct Led;
178//! # impl Led {
179//! # pub fn off(&self) {}
180//! # pub fn on(&self) {}
181//! # }
182//! # pub struct Serial;
183//! # impl Serial {
184//! # pub fn read(&self) -> nb::Result<u8, ()> { Ok(0) }
185//! # pub fn write(&self, _: u8) -> nb::Result<(), ()> { Ok(()) }
186//! # }
187//! # pub struct Timer;
188//! # impl Timer {
189//! # pub fn wait(&self) -> nb::Result<(), !> { Ok(()) }
190//! # }
191//! # }
192//! ```
193//!
194//! ## `futures`
195//!
196//! Blinks an LED every second *and* loops back serial data. Both tasks run
197//! concurrently.
198//!
199//! ```
200//! #![feature(conservative_impl_trait)]
201//! #![feature(never_type)]
202//!
203//! extern crate futures;
204//! #[macro_use(try_nb)]
205//! extern crate nb;
206//!
207//! use futures::{Async, Future};
208//! use futures::future::{self, Loop};
209//! use hal::{Error, Led, Serial, Timer};
210//!
211//! /// `futures` version of `Timer.wait`
212//! ///
213//! /// This returns a future that must be polled to completion
214//! fn wait() -> impl Future<Item = (), Error = !> {
215//! future::poll_fn(|| {
216//! Ok(Async::Ready(try_nb!(Timer.wait())))
217//! })
218//! }
219//!
220//! /// `futures` version of `Serial.read`
221//! ///
222//! /// This returns a future that must be polled to completion
223//! fn read() -> impl Future<Item = u8, Error = Error> {
224//! future::poll_fn(|| {
225//! Ok(Async::Ready(try_nb!(Serial.read())))
226//! })
227//! }
228//!
229//! /// `futures` version of `Serial.write`
230//! ///
231//! /// This returns a future that must be polled to completion
232//! fn write(byte: u8) -> impl Future<Item = (), Error = Error> {
233//! future::poll_fn(move || {
234//! Ok(Async::Ready(try_nb!(Serial.write(byte))))
235//! })
236//! }
237//!
238//! fn main() {
239//! // Tasks
240//! let mut blinky = future::loop_fn::<_, (), _, _>(true, |state| {
241//! wait().map(move |_| {
242//! if state {
243//! Led.on();
244//! } else {
245//! Led.off();
246//! }
247//!
248//! Loop::Continue(!state)
249//! })
250//! });
251//!
252//! let mut loopback = future::loop_fn::<_, (), _, _>((), |_| {
253//! read().and_then(|byte| {
254//! write(byte)
255//! }).map(|_| {
256//! Loop::Continue(())
257//! })
258//! });
259//!
260//! // Event loop
261//! loop {
262//! blinky.poll().unwrap(); // NOTE(unwrap) E = !
263//! loopback.poll().unwrap();
264//! # break
265//! }
266//! }
267//!
268//! # mod hal {
269//! # use nb;
270//! # pub struct Led;
271//! # impl Led {
272//! # pub fn off(&self) {panic!()}
273//! # pub fn on(&self) {}
274//! # }
275//! # #[derive(Debug)]
276//! # pub enum Error {}
277//! # pub struct Serial;
278//! # impl Serial {
279//! # pub fn read(&self) -> nb::Result<u8, Error> { Err(nb::Error::WouldBlock) }
280//! # pub fn write(&self, _: u8) -> nb::Result<(), Error> { Err(nb::Error::WouldBlock) }
281//! # }
282//! # pub struct Timer;
283//! # impl Timer {
284//! # pub fn wait(&self) -> nb::Result<(), !> { Err(nb::Error::WouldBlock) }
285//! # }
286//! # }
287//! ```
288//!
289//! ## `await!`
290//!
291//! This is equivalent to the `futures` example but with much less boilerplate.
292//!
293//! ```
294//! #![feature(generator_trait)]
295//! #![feature(generators)]
296//! #![feature(never_type)]
297//!
298//! #[macro_use(await)]
299//! extern crate nb;
300//!
301//! use std::ops::Generator;
302//!
303//! use hal::{Led, Serial, Timer};
304//!
305//! fn main() {
306//! // Tasks
307//! let mut blinky = || {
308//! let mut state = false;
309//! loop {
310//! // `await!` means suspend / yield instead of blocking
311//! await!(Timer.wait()).unwrap(); // NOTE(unwrap) E = !
312//!
313//! state = !state;
314//!
315//! if state {
316//! Led.on();
317//! } else {
318//! Led.off();
319//! }
320//! }
321//! };
322//!
323//! let mut loopback = || {
324//! loop {
325//! let byte = await!(Serial.read()).unwrap();
326//! await!(Serial.write(byte)).unwrap();
327//! }
328//! };
329//!
330//! // Event loop
331//! loop {
332//! blinky.resume();
333//! loopback.resume();
334//! # break
335//! }
336//! }
337//!
338//! # mod hal {
339//! # use nb;
340//! # pub struct Led;
341//! # impl Led {
342//! # pub fn off(&self) {}
343//! # pub fn on(&self) {}
344//! # }
345//! # pub struct Serial;
346//! # impl Serial {
347//! # pub fn read(&self) -> nb::Result<u8, ()> { Err(nb::Error::WouldBlock) }
348//! # pub fn write(&self, _: u8) -> nb::Result<(), ()> { Err(nb::Error::WouldBlock) }
349//! # }
350//! # pub struct Timer;
351//! # impl Timer {
352//! # pub fn wait(&self) -> nb::Result<(), !> { Err(nb::Error::WouldBlock) }
353//! # }
354//! # }
355//! ```
356
357#![no_std]
358#![doc(html_root_url = "https://docs.rs/nb/0.1.3")]
359
360extern crate nb;
361pub use nb::{block, Error, Result};
362
363/// Await operation (*won't work until the language gains support for
364/// generators*)
365///
366/// This macro evaluates the expression `$e` *cooperatively* yielding control
367/// back to the (generator) caller whenever `$e` evaluates to
368/// `Error::WouldBlock`.
369///
370/// # Requirements
371///
372/// This macro must be called within a generator body.
373///
374/// # Input
375///
376/// An expression `$e` that evaluates to `nb::Result<T, E>`
377///
378/// # Output
379///
380/// - `Ok(t)` if `$e` evaluates to `Ok(t)`
381/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))`
382#[cfg(feature = "unstable")]
383#[macro_export]
384macro_rules! await {
385 ($e:expr) => {
386 loop {
387 #[allow(unreachable_patterns)]
388 match $e {
389 Err($crate::Error::Other(e)) =>
390 {
391 #[allow(unreachable_code)]
392 break Err(e)
393 }
394 Err($crate::Error::WouldBlock) => {} // yield (see below)
395 Ok(x) => break Ok(x),
396 }
397
398 yield
399 }
400 };
401}
402
403/// Future adapter
404///
405/// This is a *try* operation from a `nb::Result` to a `futures::Poll`
406///
407/// # Requirements
408///
409/// This macro must be called within a function / closure that has signature
410/// `fn(..) -> futures::Poll<T, E>`.
411///
412/// This macro requires that the [`futures`] crate is in the root of the crate.
413///
414/// [`futures`]: https://crates.io/crates/futures
415///
416/// # Input
417///
418/// An expression `$e` that evaluates to `nb::Result<T, E>`
419///
420/// # Early return
421///
422/// - `Ok(Async::NotReady)` if `$e` evaluates to `Err(nb::Error::WouldBlock)`
423/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))`
424///
425/// # Output
426///
427/// `t` if `$e` evaluates to `Ok(t)`
428#[cfg(feature = "unstable")]
429#[macro_export]
430macro_rules! try_nb {
431 ($e:expr) => {
432 match $e {
433 Err($crate::Error::Other(e)) => return Err(e),
434 Err($crate::Error::WouldBlock) => return Ok(::futures::Async::NotReady),
435 Ok(x) => x,
436 }
437 };
438}
439