From da5757a71b7dab140b30c1a7bb94d5d2394a0490 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <jorge@japaric.io>
Date: Tue, 31 Oct 2017 17:59:47 +0100
Subject: [PATCH] add examples and cfail tests

---
 src/lib.rs              | 143 ++++++++++++++++++++++++++++++++++++++++
 src/ring_buffer/spsc.rs |  13 ++++
 2 files changed, 156 insertions(+)

diff --git a/src/lib.rs b/src/lib.rs
index 4c4abf2..c6228e5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,148 @@
 //! `static` friendly data structures that don't require dynamic memory
 //! allocation
+//!
+//! # Examples
+//!
+//! ## `Vec`
+//!
+//! ```
+//! use heapless::Vec;
+//!
+//! let mut xs: Vec<u8, [u8; 4]> = Vec::new();
+//!
+//! assert!(xs.push(0).is_ok());
+//! assert!(xs.push(1).is_ok());
+//! assert!(xs.push(2).is_ok());
+//! assert!(xs.push(3).is_ok());
+//! assert!(xs.push(4).is_err()); // full
+//!
+//! assert_eq!(xs.pop(), Some(3));
+//! ```
+//!
+//! ## `RingBuffer`
+//!
+//! ```
+//! use heapless::RingBuffer;
+//!
+//! let mut rb: RingBuffer<u8, [u8; 4]> = RingBuffer::new();
+//!
+//! assert!(rb.enqueue(0).is_ok());
+//! assert!(rb.enqueue(1).is_ok());
+//! assert!(rb.enqueue(2).is_ok());
+//! assert!(rb.enqueue(3).is_err()); // full
+//!
+//! assert_eq!(rb.dequeue(), Some(0));
+//! ```
+//!
+//! ### Single producer single consumer mode
+//!
+//! For use in *single core* systems like microcontrollers
+//!
+//! ```
+//! use heapless::RingBuffer;
+//!
+//! static mut RB: RingBuffer<Event, [Event; 4]> = RingBuffer::new();
+//!
+//! enum Event { A, B }
+//!
+//! fn main() {
+//!     // NOTE(unsafe) beware of aliasing the `consumer` end point
+//!     let mut consumer = unsafe { RB.split().1 };
+//!
+//!     loop {
+//!         // `dequeue` is a lockless operation
+//!         match consumer.dequeue() {
+//!             Some(Event::A) => { /* .. */ },
+//!             Some(Event::B) => { /* .. */ },
+//!             None => { /* sleep */},
+//!         }
+//! #       break
+//!     }
+//! }
+//!
+//! // this is a different execution context that can preempt `main`
+//! fn interrupt_handler() {
+//!     // NOTE(unsafe) beware of aliasing the `producer` end point
+//!     let mut producer = unsafe { RB.split().0 };
+//! #   let condition = true;
+//!
+//!     // ..
+//!
+//!     if condition {
+//!         producer.enqueue(Event::A).unwrap();
+//!     } else {
+//!         producer.enqueue(Event::B).unwrap();
+//!     }
+//!
+//!     // ..
+//! }
+//! ```
+//!
+//! # `Send`-ness
+//!
+//! Collections of `Send`-able things are `Send`
+//!
+//! ```
+//! use heapless::{RingBuffer, Vec};
+//! use heapless::ring_buffer::{Consumer, Producer};
+//!
+//! struct IsSend;
+//!
+//! unsafe impl Send for IsSend {}
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Consumer<IsSend, [IsSend; 4]>>();
+//! is_send::<Producer<IsSend, [IsSend; 4]>>();
+//! is_send::<RingBuffer<IsSend, [IsSend; 4]>>();
+//! is_send::<Vec<IsSend, [IsSend; 4]>>();
+//! ```
+//!
+//! Collections of not `Send`-able things are *not* `Send`
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::ring_buffer::Consumer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Consumer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::ring_buffer::Producer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Producer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::RingBuffer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<RingBuffer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::Vec;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Vec<NotSend, [NotSend; 4]>>();
+//! ```
 
 #![deny(missing_docs)]
 #![feature(const_fn)]
diff --git a/src/ring_buffer/spsc.rs b/src/ring_buffer/spsc.rs
index 1258cce..37c0671 100644
--- a/src/ring_buffer/spsc.rs
+++ b/src/ring_buffer/spsc.rs
@@ -56,6 +56,12 @@ where
     }
 }
 
+unsafe impl<T, A> Send for Consumer<T, A>
+where
+    A: Unsize<[T]>,
+    T: Send,
+{
+}
 
 /// A ring buffer "producer"; it can enqueue items into the ring buffer
 // NOTE the producer semantically owns the `tail` pointer of the ring buffer
@@ -94,6 +100,13 @@ where
     }
 }
 
+unsafe impl<T, A> Send for Producer<T, A>
+where
+    A: Unsize<[T]>,
+    T: Send,
+{
+}
+
 #[cfg(test)]
 mod tests {
     use RingBuffer;
-- 
GitLab