From fb0d26fb4ad13340a98adadd0107ee8c260ee83b Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Wed, 24 Apr 2019 11:48:51 -0700 Subject: [PATCH] Add Cursive::take_user_data --- src/cursive.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/cursive.rs b/src/cursive.rs index 2c75d52..7daad73 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -214,15 +214,63 @@ impl Cursive { /// Attempts to access the user-provided data. /// - /// If some data was set previously with the same type, returns a reference to it. + /// If some data was set previously with the same type, returns a + /// reference to it. + /// /// If nothing was set or if the type is different, returns `None`. pub fn user_data(&mut self) -> Option<&mut T> { self.user_data.downcast_mut() } + /// Attemps to take by value the current user-data. + /// + /// If successful, this will replace the current user-data with the unit + /// type `()`. + /// + /// If the current user data is not of the requested type, `None` will be + /// returned. + /// + /// # Examples + /// + /// ```rust + /// let mut siv = cursive::Cursive::dummy(); + /// + /// // Start with a simple `Vec` as user data. + /// siv.set_user_data(vec![1i32, 2, 3]); + /// assert_eq!(siv.user_data::>(), Some(&mut vec![1i32, 2, 3])); + /// + /// // Let's mutate the data a bit. + /// siv.with_user_data(|numbers: &mut Vec| numbers.push(4)); + /// + /// // If mutable reference is not enough, we can take the data by value. + /// let data: Vec = siv.take_user_data().unwrap(); + /// assert_eq!(data, vec![1i32, 2, 3, 4]); + /// + /// // At this point the user data was removed and is no longer available. + /// assert_eq!(siv.user_data::>(), None); + /// ``` + pub fn take_user_data(&mut self) -> Option { + // Start by taking the user data and replacing it with a dummy. + let user_data = std::mem::replace(&mut self.user_data, Box::new(())); + + // Downcast the data to the requested type. + // If it works, unbox it. + // It if doesn't, take it back. + user_data + .downcast() + .map_err(|user_data| { + // If we asked for the wrong type, put it back. + self.user_data = user_data; + }) + .map(|boxed| *boxed) + .ok() + } + /// Runs the given closure on the stored user data, if any. /// - /// If no user data was supplied, or if the type is different, nothing will be run. + /// If no user data was supplied, or if the type is different, nothing + /// will be run. + /// /// Otherwise, the result will be returned. pub fn with_user_data(&mut self, f: F) -> Option where