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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
//! Minimal and reusable non-blocking I/O layer
//!
//! The ultimate goal of this crate is *code reuse*. With this crate you can
//! write *core* I/O APIs that can then be adapted to operate in either blocking
//! or non-blocking manner. Furthermore those APIs are not tied to a particular
//! asynchronous model and can be adapted to work with the `futures` model or
//! with the `async` / `await` model.
//!
//! # Core idea
//!
//! The [`WouldBlock`](enum.Error.html) error variant signals that the operation
//! can't be completed *right now* and would need to block to complete.
//! [`WouldBlock`](enum.Error.html) is a special error in the sense that's not
//! *fatal*; the operation can still be completed by retrying again later.
//!
//! [`nb::Result`](type.Result.html) is based on the API of
//! [`std::io::Result`](https://doc.rust-lang.org/std/io/type.Result.html),
//! which has a `WouldBlock` variant in its
//! [`ErrorKind`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html).
//!
//! We can map [`WouldBlock`](enum.Error.html) to different blocking and
//! non-blocking models:
//!
//! - In blocking mode: [`WouldBlock`](enum.Error.html) means try again right
//!   now (i.e. busy wait)
//! - In `futures` mode: [`WouldBlock`](enum.Error.html) means
//!   [`Async::NotReady`](https://docs.rs/futures)
//! - In `await` mode: [`WouldBlock`](enum.Error.html) means `yield`
//!   (suspend the generator)
//!
//! # How to use this crate
//!
//! Application specific errors can be put inside the `Other` variant in the
//! [`nb::Error`](enum.Error.html) enum.
//!
//! So in your API instead of returning `Result<T, MyError>` return
//! `nb::Result<T, MyError>`
//!
//! ```
//! enum MyError {
//!     ThisError,
//!     ThatError,
//!     // ..
//! }
//!
//! // This is a blocking function, so it returns a normal `Result`
//! fn before() -> Result<(), MyError> {
//!     // ..
//! #   Ok(())
//! }
//!
//! // This is now a potentially (read: *non*) blocking function so it returns `nb::Result`
//! // instead of blocking
//! fn after() -> nb::Result<(), MyError> {
//!     // ..
//! #   Ok(())
//! }
//! ```
//!
//! You can use the *never type* (`!`) to signal that some API has no fatal
//! errors but may block:
//!
//! ```
//! #![feature(never_type)]
//!
//! // This returns `Ok(())` or `Err(nb::Error::WouldBlock)`
//! fn maybe_blocking_api() -> nb::Result<(), !> {
//!     // ..
//! #   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.
//!
//! [`block!`]: macro.block.html
//! [`try_nb!`]: macro.try_nb.html
//! [`await!`]: macro.await.html
//!
//! # Examples
//!
//! ## A Core I/O API
//!
//! Imagine the code (crate) below represents a Hardware Abstraction Layer for some microcontroller
//! (or microcontroller family).
//!
//! *In this and the following examples let's assume for simplicity that peripherals are treated
//! as global singletons and that no preemption is possible (i.e. interrupts are disabled).*
//!
//! ```
//! #![feature(never_type)]
//!
//! // This is the `hal` crate
//! // Note that it doesn't depend on the `futures` crate
//!
//! extern crate nb;
//!
//! /// An LED
//! pub struct Led;
//!
//! impl Led {
//!     pub fn off(&self) {
//!         // ..
//!     }
//!     pub fn on(&self) {
//!         // ..
//!     }
//! }
//!
//! /// Serial interface
//! pub struct Serial;
//! pub enum Error {
//!     Overrun,
//!     // ..
//! }
//!
//! impl Serial {
//!     /// Reads a single byte from the serial interface
//!     pub fn read(&self) -> nb::Result<u8, Error> {
//!         // ..
//! #       Ok(0)
//!     }
//!
//!     /// Writes a single byte to the serial interface
//!     pub fn write(&self, byte: u8) -> nb::Result<(), Error> {
//!         // ..
//! #       Ok(())
//!     }
//! }
//!
//! /// A timer used for timeouts
//! pub struct Timer;
//!
//! 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
//!         //  other form of error
//!
//!         // ..
//! #       Ok(())
//!     }
//! }
//! ```
//!
//! ## Blocking mode
//!
//! Turn on an LED for one second and *then* loops back serial data.
//!
//! ```
//! # #![feature(never_type)]
//! #[macro_use(block)]
//! extern crate nb;
//!
//! use hal::{Led, Serial, Timer};
//!
//! fn main() {
//!     // Turn the LED on for one second
//!     Led.on();
//!     block!(Timer.wait()).unwrap(); // NOTE(unwrap) E = !
//!     Led.off();
//!
//!     // Serial interface loopback
//!     # return;
//!     loop {
//!         let byte = block!(Serial.read()).unwrap();
//!         block!(Serial.write(byte)).unwrap();
//!     }
//! }
//!
//! # 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<u8, ()> { Ok(0) }
//! #       pub fn write(&self, _: u8) -> nb::Result<(), ()> { Ok(()) }
//! #   }
//! #   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<Item = (), Error = !> {
//!     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<Item = u8, Error = Error> {
//!     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<Item = (), Error = Error> {
//!     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<u8, Error> { 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;
//!
//! use std::ops::Generator;
//!
//! 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();
//!         }
//!     };
//!
//!     // 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<u8, ()> { 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) }
//! #   }
//! # }
//! ```

#![no_std]
#![deny(warnings)]

use core::fmt;

/// A non-blocking result
pub type Result<T, E> = ::core::result::Result<T, Error<E>>;

/// A non-blocking error
///
/// The main use of this enum is to add a `WouldBlock` variant to an existing
/// error enum.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Error<E> {
    /// A different kind of error
    Other(E),
    /// This operation requires blocking behavior to complete
    WouldBlock,
}

impl<E> fmt::Debug for Error<E>
where
    E: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Other(ref e) => fmt::Debug::fmt(e, f),
            Error::WouldBlock => f.write_str("WouldBlock"),
        }
    }
}

/// 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<T, E>`
///
/// # 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
/// longer returns `Error::WouldBlock`
///
/// # Input
///
/// An expression `$e` that evaluates to `nb::Result<T, E>`
///
/// # Output
///
/// - `Ok(t)` if `$e` evaluates to `Ok(t)`
/// - `Err(e)` if `$e` evaluates to `Err(nb::Error::Other(e))`
#[macro_export]
macro_rules! block {
    ($e:expr) => {
        loop {
            #[allow(unreachable_patterns)]
            match $e {
                Err($crate::Error::Other(e)) => {
                    #[allow(unreachable_code)]
                    break Err(e)
                },
                Err($crate::Error::WouldBlock) => {},
                Ok(x) => break Ok(x),
            }
        }
    }
}

/// 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<T, E>`.
///
/// 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<T, E>`
///
/// # 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,
        }
    }
}