1#[macro_export]
27macro_rules! impl_as_ref {
28 ($this:ident $(<$($generic:ident),+>)? => $inner:ty) => {
29 impl $(<$($generic),+>)? ::core::convert::AsRef<$inner> for $this $(<$($generic),+>)? {
30 fn as_ref(&self) -> &$inner {
31 &self.0
32 }
33 }
34 };
35
36 ($this:ident $(<$($generic:ident),+>)? => $field:ident : $inner:ty) => {
37 impl $(<$($generic),+>)? ::core::convert::AsRef<$inner> for $this $(<$($generic),+>)? {
38 fn as_ref(&self) -> &$inner {
39 &self.$field
40 }
41 }
42 };
43}
44
45#[macro_export]
73macro_rules! forward_as_ref {
74 (<$($generic:ident),+> in $this:ty => $target:ty) => {
75 impl <$($generic),+> ::core::convert::AsRef<$target> for $this {
76 fn as_ref(&self) -> &$target {
77 ::core::convert::AsRef::<$target>::as_ref(&self.0)
78 }
79 }
80 };
81
82 (<$($generic:ident),+> in $this:ty => $field:ident : $target:ty) => {
83 impl <$($generic),+> ::core::convert::AsRef<$target> for $this {
84 fn as_ref(&self) -> &$target {
85 ::core::convert::AsRef::<$target>::as_ref(&self.$field)
86 }
87 }
88 };
89
90 ($this:ty => $target:ty) => {
91 impl ::core::convert::AsRef<$target> for $this {
92 fn as_ref(&self) -> &$target {
93 ::core::convert::AsRef::<$target>::as_ref(&self.0)
94 }
95 }
96 };
97
98 ($this:ty => $field:ident : $target:ty) => {
99 impl ::core::convert::AsRef<$target> for $this {
100 fn as_ref(&self) -> &$target {
101 ::core::convert::AsRef::<$target>::as_ref(&self.$field)
102 }
103 }
104 };
105}
106
107#[macro_export]
143macro_rules! impl_as_mut {
144 ($this:ident $(<$($generic:ident),+>)? => $inner:ty) => {
145 impl $(<$($generic),+>)? ::core::convert::AsMut<$inner> for $this $(<$($generic),+>)? {
146 fn as_mut(&mut self) -> &mut $inner {
147 &mut self.0
148 }
149 }
150 };
151
152 ($this:ident $(<$($generic:ident),+>)? => $field:ident : $inner:ty) => {
153 impl $(<$($generic),+>)? ::core::convert::AsMut<$inner> for $this $(<$($generic),+>)? {
154 fn as_mut(&mut self) -> &mut $inner {
155 &mut self.$field
156 }
157 }
158 };
159}
160
161#[macro_export]
193macro_rules! forward_as_mut {
194 (<$($generic:ident),+> in $this:ty => $target:ty) => {
195 impl <$($generic),+> ::core::convert::AsMut<$target> for $this {
196 fn as_mut(&mut self) -> &mut $target {
197 ::core::convert::AsMut::<$target>::as_mut(&mut self.0)
198 }
199 }
200 };
201
202 (<$($generic:ident),+> in $this:ty => $field:ident : $target:ty) => {
203 impl <$($generic),+> ::core::convert::AsMut<$target> for $this {
204 fn as_mut(&mut self) -> &mut $target {
205 ::core::convert::AsMut::<$target>::as_mut(&mut self.$field)
206 }
207 }
208 };
209
210 ($this:ty => $target:ty) => {
211 impl ::core::convert::AsMut<$target> for $this {
212 fn as_mut(&mut self) -> &mut $target {
213 ::core::convert::AsMut::<$target>::as_mut(&mut self.0)
214 }
215 }
216 };
217
218 ($this:ty => $field:ident : $target:ty) => {
219 impl ::core::convert::AsMut<$target> for $this {
220 fn as_mut(&mut self) -> &mut $target {
221 ::core::convert::AsMut::<$target>::as_mut(&mut self.$field)
222 }
223 }
224 };
225}
226
227#[macro_export]
246macro_rules! forward_as_ref_and_mut {
247 (<$($generic:ident),+> in $this:ty => $target:ty) => {
248 $crate::forward_as_ref!(<$($generic),+> in $this => $target);
249 $crate::forward_as_mut!(<$($generic),+> in $this => $target);
250 };
251
252 (<$($generic:ident),+> in $this:ty => $field:ident : $target:ty) => {
253 $crate::forward_as_ref!(<$($generic),+> in $this => $field: $target);
254 $crate::forward_as_mut!(<$($generic),+> in $this => $field: $target);
255 };
256
257 ($this:ty => $target:ty) => {
258 $crate::forward_as_ref!($this => $target);
259 $crate::forward_as_mut!($this => $target);
260 };
261
262 ($this:ty => $field:ident : $target:ty) => {
263 $crate::forward_as_ref!($this => $field: $target);
264 $crate::forward_as_mut!($this => $field: $target);
265 };
266}
267
268#[cfg(test)]
269mod tests {
270 use alloc::{string::String, vec, vec::Vec};
271
272 struct Newtype(String);
273 forward_as_ref!(Newtype => str);
274 forward_as_mut!(Newtype => str);
275
276 struct Generic<T>(Vec<T>);
277 forward_as_ref!(<T> in Generic<T> => [T]);
278 forward_as_mut!(<T> in Generic<T> => [T]);
279
280 struct GenericNamed<T> {
281 inner: Vec<T>,
282 }
283 forward_as_ref_and_mut!(<T> in GenericNamed<T> => inner: [T]);
284
285 static_assertions::assert_impl_all!(Newtype: AsRef<str>, AsMut<str>);
286 static_assertions::assert_impl_all!(Generic<usize>: AsRef<[usize]>, AsMut<[usize]>);
287 static_assertions::assert_impl_all!(GenericNamed<usize>: AsRef<[usize]>, AsMut<[usize]>);
288
289 #[test]
290 fn forwards_newtype() {
291 let mut value = Newtype("hello".into());
292 AsMut::<str>::as_mut(&mut value).make_ascii_uppercase();
293
294 assert_eq!(AsRef::<str>::as_ref(&value), "HELLO");
295 }
296
297 #[test]
298 fn forwards_generic_newtype() {
299 let mut value = Generic(vec![1, 2, 3]);
300 AsMut::<[usize]>::as_mut(&mut value).reverse();
301
302 assert_eq!(AsRef::<[usize]>::as_ref(&value), &[3, 2, 1]);
303 }
304
305 #[test]
306 fn forwards_generic_named_field() {
307 let mut value = GenericNamed {
308 inner: vec![1, 2, 3],
309 };
310 AsMut::<[usize]>::as_mut(&mut value).reverse();
311
312 assert_eq!(AsRef::<[usize]>::as_ref(&value), &[3, 2, 1]);
313 }
314}