diff options
Diffstat (limited to 'src/libsyntax/ptr.rs')
| -rw-r--r-- | src/libsyntax/ptr.rs | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index bb47d9b535b..9fbc64758da 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -72,7 +72,7 @@ impl<T: 'static> P<T> { *self.ptr } - /// Transform the inner value, consuming `self` and producing a new `P<T>`. + /// Produce a new `P<T>` from `self` without reallocating. pub fn map<F>(mut self, f: F) -> P<T> where F: FnOnce(T) -> T, { @@ -88,8 +88,30 @@ impl<T: 'static> P<T> { ptr::write(p, f(ptr::read(p))); // Recreate self from the raw pointer. - P { - ptr: Box::from_raw(p) + P { ptr: Box::from_raw(p) } + } + } + + /// Optionally produce a new `P<T>` from `self` without reallocating. + pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where + F: FnOnce(T) -> Option<T>, + { + let p: *mut T = &mut *self.ptr; + + // Leak self in case of panic. + // FIXME(eddyb) Use some sort of "free guard" that + // only deallocates, without dropping the pointee, + // in case the call the `f` below ends in a panic. + mem::forget(self); + + unsafe { + if let Some(v) = f(ptr::read(p)) { + ptr::write(p, v); + + // Recreate self from the raw pointer. + Some(P { ptr: Box::from_raw(p) }) + } else { + None } } } |
