some_mut/
lib.rs

1//! A utility library that mainly lets you access a `Some` and then `take()` it infallibly.
2//!
3//! Useful, for example, in a `Future` implementation, when you might re-enter into
4//! a function multiple times and so can't `take()` until a sub-future is `Ready`:
5//!
6//! ```
7//! # use std::task::{ready, Context, Poll};
8//! # use std::pin::Pin;
9//! use some_mut::OptionExt;
10//! # type Error = ();
11//! # struct X { buffered_item: Option<u32>, sink: Sink }
12//! # impl X {
13//! # fn project(&mut self) -> &mut Self { self }
14//! // for a theoretical `StreamExt::forward()`/`SinkExt::send_all()` implementation:
15//! fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
16//!     let me = self.project();
17//!     if let Some(buffered_item) = me.buffered_item.some_mut() {
18//!         ready!(me.sink.poll_ready(cx))?;
19//!         me.sink.start_send(buffered_item.take())?;
20//!     }
21//!     // ...
22//! #   Poll::Ready(Ok(()))
23//! }
24//! # }
25//! # struct Sink;
26//! # impl Sink {
27//! #     fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Error>> { Poll::Ready(Ok(())) }
28//! #     fn start_send(&mut self, _item: u32) -> Result<(), Error> { Ok(()) }
29//! # }
30//! ```
31
32#![no_std]
33#![deny(missing_docs)]
34
35use core::borrow::Borrow;
36use core::fmt;
37use core::ops::{Deref, DerefMut};
38
39/// A mutable reference to an `Option` that is guaranteed to always be `Some`.
40pub struct SomeMut<'a, T>(
41    /// INVARIANT: must always be Option::Some
42    &'a mut Option<T>,
43);
44
45mod sealed {
46    pub trait Sealed {}
47}
48
49/// An extension trait that allows one to obtain a [`SomeMut`].
50pub trait OptionExt<T>: sealed::Sealed {
51    /// Obtain a `SomeMut<T>` from a `&mut Option<T>`.
52    ///
53    /// See also [`Option::as_mut()`] if [`take()`][Option::take]ing isn't required.
54    fn some_mut(&mut self) -> Option<SomeMut<'_, T>>;
55}
56
57impl<T> sealed::Sealed for Option<T> {}
58impl<T> OptionExt<T> for Option<T> {
59    fn some_mut(&mut self) -> Option<SomeMut<'_, T>> {
60        match self {
61            x @ Some(_) => Some(SomeMut(x)),
62            None => None,
63        }
64    }
65}
66
67impl<'a, T> SomeMut<'a, T> {
68    /// Take the value from this `SomeMut`, leaving a `None` in the original option.
69    ///
70    /// # Examples
71    ///
72    /// ```
73    /// use some_mut::OptionExt;
74    ///
75    /// let mut x = Some(vec![42, 10, 12]);
76    /// let mut y = 0;
77    /// let mut z = vec![];
78    /// for i in 0..5 {
79    ///     if let Some(x) = x.some_mut() {
80    ///         y += 2;
81    ///         if y >= 4 {
82    ///             z = x.take();
83    ///         }
84    ///     } else {
85    ///         z.push(i)
86    ///     }
87    /// }
88    ///
89    /// assert!(x.is_none());
90    /// assert_eq!(y, 4);
91    /// assert_eq!(z, [42, 10, 12, 2, 3, 4])
92    /// ```
93    pub fn take(self) -> T {
94        // SAFETY: safety invariant on SomeMut
95        unsafe { self.0.take().unwrap_unchecked() }
96    }
97
98    /// Unwrap this `SomeMut` into a normal mutable reference, with a lifetime tied to the original option.
99    pub fn into_mut(self) -> &'a mut T {
100        // SAFETY: safety invariant on SomeMut
101        unsafe { self.0.as_mut().unwrap_unchecked() }
102    }
103
104    /// Unwrap this `SomeMut` into a mutable reference to the original option.
105    pub fn into_option_mut(self) -> &'a mut Option<T> {
106        self.0
107    }
108}
109
110impl<T> Deref for SomeMut<'_, T> {
111    type Target = T;
112    fn deref(&self) -> &T {
113        // SAFETY: safety invariant on SomeMut
114        unsafe { self.0.as_ref().unwrap_unchecked() }
115    }
116}
117
118impl<T> DerefMut for SomeMut<'_, T> {
119    fn deref_mut(&mut self) -> &mut Self::Target {
120        // SAFETY: safety invariant on SomeMut
121        unsafe { self.0.as_mut().unwrap_unchecked() }
122    }
123}
124
125impl<T: fmt::Debug> fmt::Debug for SomeMut<'_, T> {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        (**self).fmt(f)
128    }
129}
130
131impl<T: fmt::Display> fmt::Display for SomeMut<'_, T> {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        (**self).fmt(f)
134    }
135}
136
137impl<T> Borrow<T> for SomeMut<'_, T> {
138    fn borrow(&self) -> &T {
139        self
140    }
141}
142
143impl<T> AsRef<T> for SomeMut<'_, T> {
144    fn as_ref(&self) -> &T {
145        self
146    }
147}
148
149impl<T> AsMut<T> for SomeMut<'_, T> {
150    fn as_mut(&mut self) -> &mut T {
151        self
152    }
153}
154
155impl<T: PartialEq> PartialEq<T> for SomeMut<'_, T> {
156    fn eq(&self, other: &T) -> bool {
157        T::eq(self, other)
158    }
159}
160
161impl<T: PartialOrd> PartialOrd<T> for SomeMut<'_, T> {
162    fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
163        T::partial_cmp(self, other)
164    }
165}