empty_option/
lib.rs

1//! This crate provides convenient wrappers for dealing with `&mut Option<T>`. There are two main types, `OptionGuard` and `OptionGuardMut`:
2//! 
3//! ## `OptionGuard`
4//! 
5//! Using `EmptyOptionExt::steal` on an `&mut Option<T>` produces the `T` from the option as well as an `OptionGuard`. If `OptionGuard::restore` is not called before the `OptionGuard` is dropped, then a panic will occur.
6//! 
7//! ### Examples
8//! 
9//! Calling `guard.restore()` puts the stolen value back into the original option:
10//! 
11//! ```rust
12//! use empty_option::EmptyOptionExt;
13//! 
14//! // A mutable option, from which we shall steal a value!
15//! let mut thing = Some(5);
16//! 
17//! // Scope so that when we do `guard.restore()`, the mutable borrow on `thing` will end.
18//! {
19//!     // Steal the value - we now have the guard and also a concrete `T` from our `Option<T>`.
20//!     let (guard, five) = thing.steal();
21//! 
22//!     assert_eq!(five, 5);
23//! 
24//!     // Move the value back into `thing` - we're done.
25//!     guard.restore(6);
26//! }
27//! 
28//! // The value is returned by `guard.restore()`.
29//! assert_eq!(thing, Some(6));
30//! ```
31//! 
32//! But, if the guard is dropped instead, a runtime panic results.
33//! 
34//! ```rust,should_panic
35//! use empty_option::EmptyOptionExt;
36//! 
37//! let mut thing = Some(5);
38//! 
39//! let (_, _) = thing.steal();
40//! 
41//! // Never return the value!
42//! ```
43//!
44//! Calling `.steal()` on a `None` immediately panics:
45//!
46//! ```rust,should_panic
47//! let mut thing = None;
48//! 
49//! // Panics here!
50//! let (guard, _) = thing.steal();
51//! 
52//! guard.restore(5);
53//! ```
54//! 
55//! ## `OptionGuardMut`
56//! 
57//! Using `EmptyOptionExt::steal_mut` on an `&mut Option<T>` produces an `OptionGuardMut`, which dereferences to a `T`. To get the inner value out, `OptionGuardMut::into_inner` can be called. On `Drop`, if the `OptionGuardMut` is not consumed with `OptionGuardMut::into_inner`, the value in the `OptionGuardMut` will be returned to the `Option` that it was borrowed from.
58//! 
59//! ### Examples
60//! 
61//! Take a value from an option, which is automatically returned:
62//! 
63//! ```rust
64//! use empty_option::EmptyOptionExt;
65//! 
66//! let mut thing = Some(5);
67//! 
68//! {
69//!     let mut stolen = thing.steal_mut();
70//! 
71//!     assert_eq!(*stolen, 5);
72//! 
73//!     *stolen = 6;
74//! }
75//! 
76//! assert_eq!(thing, Some(6));
77//! ```
78//! 
79//! If the guard is consumed, the value is never returned.
80//! 
81//! ```rust
82//! use empty_option::EmptyOptionExt;
83//! 
84//! let mut thing = Some(5);
85//! 
86//! {
87//!     // Keep the thing!
88//!     let stolen = thing.steal_mut().into_inner();
89//! 
90//!     assert_eq!(stolen, 5);
91//! }
92//! 
93//! assert_eq!(thing, None);
94//!
95//! ```
96//! 
97//! Calling `steal_mut` on a `None` immediately panics:
98//!
99//! ```rust,should_panic
100//! let mut thing: Option<i32> = None;
101//! 
102//! // Panics here!
103//! thing.steal_mut();
104//! ```
105
106use std::mem;
107use std::ops::{Deref, DerefMut};
108
109
110/// Extension trait providing nice method sugar for `steal` and `steal_mut`.
111pub trait EmptyOptionExt {
112    type Inner;
113
114    /// Take a value out of an option, providing a guard which panics if the value is not returned.
115    /// Panics on `None`.
116    fn steal(&mut self) -> (OptionGuard<Self::Inner>, Self::Inner);
117
118    /// Take a value out of an option, providing a guard which returns the value unless consumed by
119    /// `OptionGuardMut::into_inner`. Panics on `None`.
120    fn steal_mut<'a>(&'a mut self) -> OptionGuardMut<'a, Self::Inner>;
121}
122
123
124/// An option which has had its value taken. On `Drop`, `OptionGuard` will panic - in order to
125/// prevent a panic, the stolen value must be moved back in with `OptionGuard::restore`.
126///
127/// This is useful if you are using an `Option` because you have a value which you need to take,
128/// and then deal with by-value, but you want to preserve the invariant that your optional value is
129/// always present.
130/// 
131/// # Examples
132///
133/// Calling `guard.restore()` puts the stolen value back into the original option:
134///
135/// ```
136/// # use empty_option::EmptyOptionExt;
137/// // A mutable option, from which we shall steal a value!
138/// let mut thing = Some(5);
139/// 
140/// // Scope so that when we do `guard.restore()`, the mutable borrow on `thing` will end.
141/// {
142///     // Steal the value - we now have the guard and also a concrete `T` from our `Option<T>`.
143///     let (guard, five) = thing.steal();
144/// 
145///     assert_eq!(five, 5);
146/// 
147///     // Move the value back into `thing` - we're done.
148///     guard.restore(6);
149/// }
150/// 
151/// // The value is returned by `guard.restore()`.
152/// assert_eq!(thing, Some(6));
153/// ```
154///
155/// But, if the guard is dropped instead, a runtime panic results.
156///
157/// ```should_panic
158/// # use empty_option::EmptyOptionExt;
159/// let mut thing = Some(5);
160/// 
161/// let (_, _) = thing.steal();
162/// 
163/// // Never return the value!
164/// ```
165///
166/// Calling `.steal()` on a `None` immediately panics:
167///
168/// ```rust,should_panic
169/// let mut thing = None;
170/// 
171/// // Panics here!
172/// let (guard, _) = thing.steal();
173/// 
174/// guard.restore(5);
175/// ```
176pub struct OptionGuard<'a, T: 'a> {
177    opt: &'a mut Option<T>,
178}
179
180
181impl<'a, T> Drop for OptionGuard<'a, T> {
182    fn drop(&mut self) {
183        panic!("`Some` value was never restored to a victimized Option!");
184    }
185}
186
187
188impl<'a, T> OptionGuard<'a, T> {
189    fn new(opt: &'a mut Option<T>) -> OptionGuard<'a, T> {
190        OptionGuard {
191            opt
192        }
193    }
194
195
196    /// Restore a stolen value to an `Option`.
197    pub fn restore(self, obj: T) {
198        *self.opt = Some(obj);
199
200        mem::forget(self);
201    }
202}
203
204
205/// A value taken from an `Option<T>`. `OptionGuardMut<T>` dereferences to a `T`, and the inner `T`
206/// can be moved out with `OptionGuardMut::into_inner`. When dropped, the `OptionGuardMut` moves
207/// the taken value back into the `Option` it came from.
208///
209/// # Examples
210///
211/// Take a value from an option, which is automatically returned:
212///
213/// ```
214/// # use empty_option::EmptyOptionExt;
215/// let mut thing = Some(5);
216/// 
217/// {
218///     let mut stolen = thing.steal_mut();
219/// 
220///     assert_eq!(*stolen, 5);
221/// 
222///     *stolen = 6;
223/// }
224/// 
225/// assert_eq!(thing, Some(6));
226/// ```
227/// 
228/// If the guard is consumed, the value is never returned.
229///
230/// ```
231/// # use empty_option::EmptyOptionExt;
232/// let mut thing = Some(5);
233/// 
234/// {
235///     // Keep the thing!
236///     let stolen = thing.steal_mut().into_inner();
237/// 
238///     assert_eq!(stolen, 5);
239/// }
240/// 
241/// assert_eq!(thing, None);
242/// ```
243///
244/// Calling `steal_mut` on a `None` immediately panics:
245///
246/// ```rust,should_panic
247/// let mut thing: Option<i32> = None;
248/// 
249/// // Panics here!
250/// thing.steal_mut();
251/// ```
252pub struct OptionGuardMut<'a, T: 'a> {
253    origin: &'a mut Option<T>,
254    value: Option<T>,
255}
256
257
258impl<'a, T> Drop for OptionGuardMut<'a, T> {
259    fn drop(&mut self) {
260        *self.origin = self.value.take();
261    }
262}
263
264
265impl<'a, T> OptionGuardMut<'a, T> {
266    /// Keep the value stolen from the `Option` and do not return it.
267    pub fn into_inner(mut self) -> T {
268        self.value.take().unwrap()
269    }
270}
271
272
273impl<'a, T> Deref for OptionGuardMut<'a, T> {
274    type Target = T;
275
276    fn deref(&self) -> &T {
277        self.value.as_ref().unwrap()
278    }
279}
280
281
282impl<'a, T> DerefMut for OptionGuardMut<'a, T> {
283    fn deref_mut(&mut self) -> &mut T {
284        self.value.as_mut().unwrap()
285    }
286}
287
288
289impl<T> EmptyOptionExt for Option<T> {
290    type Inner = T;
291
292    fn steal(&mut self) -> (OptionGuard<T>, T) {
293        let value = self.take().expect("attempted to steal from None");
294        (OptionGuard::new(self), value)
295    }
296
297    fn steal_mut(&mut self) -> OptionGuardMut<T> {
298        let value = Some(self.take().expect("attempted to steal from None"));
299
300        OptionGuardMut {
301            origin: self,
302            value,
303        }
304    }
305}
306
307
308#[cfg(test)]
309mod tests {
310    use super::*;
311
312    #[test]
313    fn catch_and_release() {
314        let mut thing = Some(5);
315
316        {
317            let (guard, five) = thing.steal();
318
319            assert_eq!(five, 5);
320
321            guard.restore(6);
322        }
323
324        assert_eq!(thing, Some(6));
325    }
326
327    #[test]
328    #[should_panic]
329    fn catch_and_keep() {
330        let mut thing = Some(5);
331
332        let (_, _) = thing.steal();
333
334        // Never return the value!
335    }
336
337    #[test]
338    #[should_panic]
339    fn catch_from_none() {
340        let mut thing = None;
341
342        let (guard, _) = thing.steal();
343
344        guard.restore(5);
345    }
346
347    #[test]
348    fn mut_and_release() {
349        let mut thing = Some(5);
350
351        {
352            let mut stolen = thing.steal_mut();
353
354            assert_eq!(*stolen, 5);
355
356            *stolen = 6;
357        }
358
359        assert_eq!(thing, Some(6));
360    }
361
362    #[test]
363    fn mut_and_keep() {
364        let mut thing = Some(5);
365        
366        {
367            // Keep the thing!
368            let stolen = thing.steal_mut().into_inner();
369
370            assert_eq!(stolen, 5);
371        }
372
373        assert_eq!(thing, None);
374    }
375
376    #[test]
377    #[should_panic]
378    fn mut_from_none() {
379        let mut thing: Option<i32> = None;
380
381        thing.steal_mut();
382    }
383}