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}