1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4extern crate alloc;
5
6#[cfg(test)]
7use alloc::vec;
8use alloc::{
9 borrow::{Cow, ToOwned},
10 collections::*,
11 ffi::CString,
12 rc::Rc,
13 string::String,
14 sync::Arc,
15 vec::Vec,
16};
17use core::{
18 cmp,
19 marker::{PhantomData, PhantomPinned},
20 mem::MaybeUninit,
21 num::*,
22 ptr::NonNull,
23 task::Poll,
24};
25#[cfg(feature = "std")]
26use std::{collections::*, ffi::OsString, path::PathBuf};
27
28pub trait StdMove: Sized {
30 #[must_use]
32 fn std_move(&mut self) -> Self;
33}
34
35#[macro_export]
37macro_rules! impl_trivial {
38 (@gen($self:ident)) => { $self.clone() };
39 (@gen($self:ident) {$($b:tt)*}) => {{ $($b)* }};
40 ($(
41 $(#[$meta:meta])*
42 $ty:ty $([$($g:tt)*])? $({$($b:tt)*})?
43 ),+ $(,)?) => {
44 $(
45 $(#[$meta])*
46 impl$(<$($g)*>)? $crate::StdMove for $ty {
47 fn std_move(&mut self) -> Self {
48 $crate::impl_trivial!(@gen(self) $({$($b)*})?)
49 }
50 }
51 )+
52 };
53}
54#[macro_export]
58macro_rules! impl_take {
59 (@gen($self:ident)) => { ::core::mem::take($self) };
60 (@gen($self:ident) {$($b:tt)*}) => {{ $($b)* }};
61 ($(
62 $(#[$meta:meta])*
63 $ty:ty $([$($g:tt)*])? $({$($b:tt)*})?
64 ),+ $(,)?) => {
65 $(
66 $(#[$meta])*
67 impl$(<$($g)*>)? $crate::StdMove for $ty {
68 fn std_move(&mut self) -> Self {
69 $crate::impl_take!(@gen(self) $({$($b)*})?)
70 }
71 }
72 )+
73 };
74}
75macro_rules! impl_tuples {
76 () => {
77 impl_tuples! { () T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 }
78 };
79 (() $cur:ident $($rest:ident)*) => {
80 impl_tuples! {
81 @impl
82 $cur
84 }
85 impl_tuples! { ($cur) $($rest)* }
86 };
87 (($($c:ident)*)) => {};
88 (($($c:ident)*) $cur:ident $($rest:ident)*) => {
89 impl_tuples! {
90 @impl
91 #[doc(hidden)]
92 $($c)* $cur
93 }
94 impl_tuples! { ($($c)* $cur) $($rest)* }
95 };
96 (@impl $(#[$meta:meta])* $($i:ident)+) => {
97 $(#[$meta])*
98 impl<$($i),+> StdMove for ($($i,)+)
99 where $($i: StdMove,)+
100 {
101 fn std_move(&mut self) -> Self {
102 #[allow(non_snake_case)]
103 let ($($i,)+) = self;
104 ($($i.std_move(),)+)
105 }
106 }
107 };
108}
109
110impl<T: StdMove, const N: usize> StdMove for [T; N] {
111 fn std_move(&mut self) -> Self {
112 self.each_mut().map(StdMove::std_move)
113 }
114}
115impl<T: StdMove> StdMove for cmp::Reverse<T> {
116 fn std_move(&mut self) -> Self {
117 Self(self.0.std_move())
118 }
119}
120impl<T: ToOwned> StdMove for Cow<'_, T> where T::Owned: StdMove {
121 fn std_move(&mut self) -> Self {
122 match self {
123 Cow::Borrowed(x) => Self::Borrowed(*x),
124 Cow::Owned(x) => Self::Owned(x.std_move()),
125 }
126 }
127}
128impl<T> StdMove for MaybeUninit<T> {
129 fn std_move(&mut self) -> Self {
130 unsafe {
131 core::ptr::read(self)
133 }
134 }
135}
136
137impl_tuples!();
138impl_trivial! {
139 (),
140 i8,
141 i16,
142 i32,
143 i64,
144 i128,
145 isize,
146 u8,
147 u16,
148 u32,
149 u64,
150 u128,
151 f32,
152 f64,
153 usize,
154 bool,
155 char,
156 NonZeroI8,
157 NonZeroI16,
158 NonZeroI32,
159 NonZeroI64,
160 NonZeroI128,
161 NonZeroIsize,
162 NonZeroU8,
163 NonZeroU16,
164 NonZeroU32,
165 NonZeroU64,
166 NonZeroU128,
167 NonZeroUsize,
168 PhantomData<T> [T: ?Sized],
169 PhantomPinned,
170 &T [T: ?Sized],
171 *mut T [T: ?Sized],
172 *const T [T: ?Sized],
173 NonNull<T> [T: ?Sized],
174 cmp::Ordering,
175 core::sync::atomic::Ordering,
176 Rc<T> [T],
177 Arc<T> [T],
178}
179impl_take! {
180 Vec<T> [T],
181 VecDeque<T> [T],
182 LinkedList<T> [T],
183 BTreeSet<T> [T],
184 BTreeMap<K, V> [K, V],
185 BinaryHeap<T> [T: Ord],
186 Option<T> [T],
187 String,
188 CString,
189 Poll<T> [T] { Poll::Pending },
190}
191#[cfg(feature = "std")]
192impl_take! {
193 HashSet<T, S> [T, S: Default],
194 HashMap<K, V, S> [K, V, S: Default],
195 OsString,
196 PathBuf,
197}
198
199#[macro_export]
224macro_rules! r#move {
225 ($e:expr) => {
226 $crate::StdMove::std_move(&mut $e)
227 };
228}
229
230#[test]
231fn it_works() {
232 let mut a = vec![1, 2, 3];
233 let b;
234 b = r#move!(a);
235 assert_eq!(a, []);
236 assert_eq!(b, [1, 2, 3]);
237
238 let mut n = 3;
239 assert_eq!(r#move!(n), 3);
240 assert_eq!(r#move!(n), 3);
241 assert_eq!(n, 3);
242}
243
244#[test]
245fn move_maybe_uninit() {
246 let mut a = MaybeUninit::new(vec![1, 2, 3]);
247 let b = r#move!(a);
248 assert_eq!(unsafe { b.assume_init() }, [1, 2, 3]);
249}