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}