From 6ed25cbe3afcee6fb14bbc95849841dd37ffcf9e Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Tue, 12 Feb 2019 10:09:31 +0100 Subject: [PATCH] tools: add Tied value Tie two dependent values together, such as a nix::Dir with its nix::dir::Iter<'a> where 'a is tied to the Dir's lifetime, making it otherwise impossible to return them or store them in a struct. Alternatively we could try the 'rental' crate. Signed-off-by: Wolfgang Bumiller --- src/tools.rs | 1 + src/tools/borrow.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/tools/borrow.rs diff --git a/src/tools.rs b/src/tools.rs index 1891719a..56a63f67 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -24,6 +24,7 @@ pub mod wrapped_reader_stream; #[macro_use] pub mod common_regex; pub mod ticket; +pub mod borrow; /// The `BufferedReader` trait provides a single function /// `buffered_read`. It returns a reference to an internal buffer. The diff --git a/src/tools/borrow.rs b/src/tools/borrow.rs new file mode 100644 index 00000000..5970828d --- /dev/null +++ b/src/tools/borrow.rs @@ -0,0 +1,45 @@ +/// This ties two values T and U together, such that T does not move and cannot be used as long as +/// there's an U. This essentially replaces the borrow checker's job for dependent values which +/// need to be stored together in a struct {}, and is similar to what the 'rental' crate produces. +pub struct Tied(Option>, Option>); + +impl Drop for Tied { + fn drop(&mut self) { + // let's be explicit about order here! + std::mem::drop(self.1.take()); + } +} + +impl Tied { + /// Takes an owner and a function producing the depending value. The owner will be inaccessible + /// until the tied value is resolved. The dependent value is only accessible by reference. + pub fn new(owner: T, producer: F) -> Self + where + F: FnOnce(*mut T) -> Box, + { + let mut owner = Box::new(owner); + let dep = producer(&mut *owner); + Tied(Some(owner), Some(dep)) + } + + pub fn into_boxed_inner(mut self) -> Box { + self.1 = None; + self.0.take().unwrap() + } + + pub fn into_inner(self) -> T { + *self.into_boxed_inner() + } +} + +impl AsRef for Tied { + fn as_ref(&self) -> &U { + self.1.as_ref().unwrap() + } +} + +impl AsMut for Tied { + fn as_mut(&mut self) -> &mut U { + self.1.as_mut().unwrap() + } +}