From 8d1825fb0d62fc0ea4143ae6eb1b606440b37561 Mon Sep 17 00:00:00 2001
From: Gav <gavin@parity.io>
Date: Wed, 10 Jan 2018 18:58:49 +0100
Subject: [PATCH] Add some docs and a test.

---
 substrate/environmental/src/lib.rs | 61 +++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs
index cd278f81233..0dcd55bdcb2 100644
--- a/substrate/environmental/src/lib.rs
+++ b/substrate/environmental/src/lib.rs
@@ -14,9 +14,38 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-use std::cell::RefCell;
+//! Safe global references to stack variables.
+//!
+//! Set up a global reference with declare_simple_environment! macro giving it a name and type.
+//! Use the `using` function scoped under its name to name a reference and call a function that
+//! takes no parameters yet can access said reference through the similarly place `with` function.
+//!
+//! # Examples
+//!
+//! ```
+//! #[macro_use] extern crate environmental;
+//! // create a place for the global reference to exist.
+//! declare_simple_environment!(counter: u32);
+//! fn stuff() {
+//!   // do some stuff, accessing the named reference as desired.
+//!   counter::with(|value| *value += 1);
+//! }
+//! fn main() {
+//!   // declare a stack variable of the same type as our global declaration.
+//!   let mut local = 41u32;
+//!   // call stuff, setting up our `counter` environment as a refrence to our local counter var.
+//!   counter::using(&mut local, stuff);
+//!   println!("The answer is {:?}", local); // will print 42!
+//!   stuff();	// safe! doesn't do anything.
+//! }
+//! ```
+
+
+pub use std::cell::RefCell;
 use std::thread::LocalKey;
 
+pub fn test_me() { panic!("Hello") }
+
 pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>(
 	global: &'static LocalKey<RefCell<*mut S>>,
 	protected: &'a mut T,
@@ -24,7 +53,7 @@ pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>(
 ) -> R {
 	// store the `protected` reference as a pointer so we can provide it to logic running within
 	// `f`.
-	// while re record this pointer (while it's non-zero) we guarantee:
+	// while we record this pointer (while it's non-zero) we guarantee:
 	// - it will only be used once at any time (no reentrancy);
 	// - that no other thread will use it; and
 	// - that we do not use the original mutating reference while the pointer.
@@ -62,7 +91,7 @@ pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>(
 macro_rules! decl_environment {
 	($name:ident : $t:ty) => {
 		thread_local! {
-			static $name: std::cell::RefCell<*mut $t> = std::cell::RefCell::new(0 as *mut $t);
+			static $name: $crate::RefCell<*mut $t> = $crate::RefCell::new(0 as *mut $t);
 		}
 	}
 }
@@ -71,6 +100,7 @@ macro_rules! decl_environment {
 macro_rules! declare_generic_environment {
 	($name:ident : $t:tt) => {
 		mod $name {
+			#[allow(unused_imports)]
 			use super::*;
 
 			decl_environment!(GLOBAL: $t<'static> );
@@ -103,6 +133,7 @@ macro_rules! declare_generic_environment {
 macro_rules! declare_simple_environment {
 	($name:ident : $t:tt) => {
 		mod $name {
+			#[allow(unused_imports)]
 			use super::*;
 
 			decl_environment!(GLOBAL: $t);
@@ -114,14 +145,14 @@ macro_rules! declare_simple_environment {
 				$crate::using_environment(&GLOBAL, protected, f)
 			}
 
-			pub fn with<R, F: for<'r> FnOnce(&'r mut $t -> R)>(
+			pub fn with<R, F: for<'r> FnOnce(&'r mut $t) -> R>(
 				f: F
 			) -> Option<R> {
 				let dummy = ();
 				with_closed(f, &dummy)
 			}
 
-			fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t -> R)>(
+			fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t) -> R>(
 				f: F,
 				_dummy: &'d (),
 			) -> Option<R> {
@@ -134,3 +165,23 @@ macro_rules! declare_simple_environment {
 // TODO: Docs
 // TODO: Example
 // TODO: Tests
+
+#[cfg(test)]
+mod tests {
+	declare_simple_environment!(counter: u32);
+
+	fn stuff() {
+		// do some stuff, accessing the named reference as desired.
+		counter::with(|value| *value += 1);
+	}
+
+	#[test]
+	fn simple_environment_works() {
+		// declare a stack variable of the same type as our global declaration.
+		let mut local = 41u32;
+		// call stuff, setting up our `counter` environment as a refrence to our local counter var.
+		counter::using(&mut local, stuff);
+		println!("The answer is {:?}", local); // will print 42!
+		stuff();	// safe! doesn't do anything.
+	}
+}
-- 
GitLab