From 426780060dee0abb47c85f839943d35a70b0af01 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 21 Dec 2019 00:53:28 +0000 Subject: chore(defer.rs): Prepare for depot merge --- fun/defer_rs/examples/defer-with-error.rs | 70 +++++++++++++++++++++++++++++++ fun/defer_rs/examples/defer.rs | 31 ++++++++++++++ fun/defer_rs/examples/undefer.rs | 40 ++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 fun/defer_rs/examples/defer-with-error.rs create mode 100644 fun/defer_rs/examples/defer.rs create mode 100644 fun/defer_rs/examples/undefer.rs (limited to 'fun/defer_rs/examples') diff --git a/fun/defer_rs/examples/defer-with-error.rs b/fun/defer_rs/examples/defer-with-error.rs new file mode 100644 index 000000000000..26d56d77cf1b --- /dev/null +++ b/fun/defer_rs/examples/defer-with-error.rs @@ -0,0 +1,70 @@ +// Go's defer in Rust, with error value return. + +use std::rc::Rc; +use std::sync::RwLock; + +struct Defer { + f: F +} + +impl Drop for Defer { + fn drop(&mut self) { + (self.f)() + } +} + +// Only added this for Go-syntax familiarity ;-) +fn defer(f: F) -> Defer { + Defer { f } +} + +// Convenience type synonym. This is a reference-counted smart pointer to +// a shareable, mutable variable. +// Rust does not allow willy-nilly mutation of shared variables, so explicit +// write-locking must be performed. +type ErrorHandle = Rc>>; + +/////////////////// +// Usage example // +/////////////////// + +#[derive(Debug)] // Debug trait for some default way to print the type. +enum Error { DropError } + +fn main() { + // Create a place to store the error. + let drop_err: ErrorHandle = Default::default(); // create empty error + + // Introduce an arbitrary scope block (so that we still have control after + // the defer runs): + { + let mut i = 1; + + // Rc types are safe to clone and share for multiple ownership. + let err_handle = drop_err.clone(); + + // Call defer and let the closure own the cloned handle to the error: + let token = defer(move || { + // do something! + println!("Value is: {}", i); + + // ... oh no, it went wrong! + *err_handle.write().unwrap() = Some(Error::DropError); + }); + + i += 1; + println!("Value is: {}", i); + + // token goes out of scope here - drop() is called. + } + + match *drop_err.read().unwrap() { + Some(ref err) => println!("Oh no, an error occured: {:?}!", err), + None => println!("Phew, everything went well.") + }; +} + +// Prints: +// Value is: 2 +// Value is: 1 +// Oh no, an error occured: DropError! diff --git a/fun/defer_rs/examples/defer.rs b/fun/defer_rs/examples/defer.rs new file mode 100644 index 000000000000..eadac795f8bc --- /dev/null +++ b/fun/defer_rs/examples/defer.rs @@ -0,0 +1,31 @@ +// Go's defer in Rust! + +struct Defer { + f: F +} + +impl Drop for Defer { + fn drop(&mut self) { + (self.f)() + } +} + +// Only added this for Go-syntax familiarity ;-) +fn defer(f: F) -> Defer { + Defer { f } +} + +fn main() { + let mut i = 1; + + // Calling it "token" ... could be something else. The lifetime of this + // controls when the action is run. + let _token = defer(move || println!("Value is: {}", i)); + + i += 1; + println!("Value is: {}", i); +} + +// Prints: +// Value is: 2 +// Value is: 1 diff --git a/fun/defer_rs/examples/undefer.rs b/fun/defer_rs/examples/undefer.rs new file mode 100644 index 000000000000..17ad8a6b5485 --- /dev/null +++ b/fun/defer_rs/examples/undefer.rs @@ -0,0 +1,40 @@ +// Go's defer in Rust, with a little twist! + +struct Defer { + f: F +} + +impl Drop for Defer { + fn drop(&mut self) { + (self.f)() + } +} + +// Only added this for Go-syntax familiarity ;-) +fn defer(f: F) -> Defer { + Defer { f } +} + +// Changed your mind about the defer? +// (Note: This leaks the closure! Don't actually do this!) +fn undefer(token: Defer) { + use std::mem; + mem::forget(token); +} + +fn main() { + let mut i = 1; + + // Calling it "token" ... could be something else. The lifetime of this + // controls when the action is run. + let token = defer(move || println!("Value is: {}", i)); + + i += 1; + println!("Value is: {}", i); + + // Oh, now I changed my mind about the previous defer: + undefer(token); +} + +// Prints: +// Value is: 2 -- cgit 1.4.1