1#[macro_export]
40macro_rules! impl_as_ref {
41 (<$($generic:ident),+> in $($rest:tt)+) => {
42 $crate::impl_as_ref!(@impl [$($generic),+] $($rest)+);
43 };
44
45 (<const $($rest:tt)+) => {
46 $crate::__impl_more_parse_generics!(@parse impl_as_ref [] [] const $($rest)+);
47 };
48
49 (<$generic:ident, $($rest:tt)+) => {
50 $crate::__impl_more_parse_generics!(@parse impl_as_ref [] [] $generic, $($rest)+);
51 };
52
53 (@impl [$($generic:tt)+] $this:ty => $inner:ty) => {
54 impl <$($generic)+> ::core::convert::AsRef<$inner> for $this {
55 fn as_ref(&self) -> &$inner {
56 &self.0
57 }
58 }
59 };
60
61 (@impl [$($generic:tt)+] $this:ty => $field:ident : $inner:ty) => {
62 impl <$($generic)+> ::core::convert::AsRef<$inner> for $this {
63 fn as_ref(&self) -> &$inner {
64 &self.$field
65 }
66 }
67 };
68
69 ($this:ident $(<$($generic:ident),+>)? => $inner:ty) => {
70 impl $(<$($generic),+>)? ::core::convert::AsRef<$inner> for $this $(<$($generic),+>)? {
71 fn as_ref(&self) -> &$inner {
72 &self.0
73 }
74 }
75 };
76
77 ($this:ident $(<$($generic:ident),+>)? => $field:ident : $inner:ty) => {
78 impl $(<$($generic),+>)? ::core::convert::AsRef<$inner> for $this $(<$($generic),+>)? {
79 fn as_ref(&self) -> &$inner {
80 &self.$field
81 }
82 }
83 };
84}
85
86#[macro_export]
116macro_rules! forward_as_ref {
117 (<$($generic:ident),+> in $($rest:tt)+) => {
118 $crate::forward_as_ref!(@impl [$($generic),+] $($rest)+);
119 };
120
121 (<const $($rest:tt)+) => {
122 $crate::__impl_more_parse_generics!(@parse forward_as_ref [] [] const $($rest)+);
123 };
124
125 (<$generic:ident, $($rest:tt)+) => {
126 $crate::__impl_more_parse_generics!(@parse forward_as_ref [] [] $generic, $($rest)+);
127 };
128
129 (@impl [$($generic:tt)+] $this:ty => $target:ty) => {
130 impl <$($generic)+> ::core::convert::AsRef<$target> for $this {
131 fn as_ref(&self) -> &$target {
132 ::core::convert::AsRef::<$target>::as_ref(&self.0)
133 }
134 }
135 };
136
137 (@impl [$($generic:tt)+] $this:ty => $field:ident : $target:ty) => {
138 impl <$($generic)+> ::core::convert::AsRef<$target> for $this {
139 fn as_ref(&self) -> &$target {
140 ::core::convert::AsRef::<$target>::as_ref(&self.$field)
141 }
142 }
143 };
144
145 ($this:ty => $target:ty) => {
146 impl ::core::convert::AsRef<$target> for $this {
147 fn as_ref(&self) -> &$target {
148 ::core::convert::AsRef::<$target>::as_ref(&self.0)
149 }
150 }
151 };
152
153 ($this:ty => $field:ident : $target:ty) => {
154 impl ::core::convert::AsRef<$target> for $this {
155 fn as_ref(&self) -> &$target {
156 ::core::convert::AsRef::<$target>::as_ref(&self.$field)
157 }
158 }
159 };
160}
161
162#[macro_export]
200macro_rules! impl_as_mut {
201 (<$($generic:ident),+> in $($rest:tt)+) => {
202 $crate::impl_as_mut!(@impl [$($generic),+] $($rest)+);
203 };
204
205 (<const $($rest:tt)+) => {
206 $crate::__impl_more_parse_generics!(@parse impl_as_mut [] [] const $($rest)+);
207 };
208
209 (<$generic:ident, $($rest:tt)+) => {
210 $crate::__impl_more_parse_generics!(@parse impl_as_mut [] [] $generic, $($rest)+);
211 };
212
213 (@impl [$($generic:tt)+] $this:ty => $inner:ty) => {
214 impl <$($generic)+> ::core::convert::AsMut<$inner> for $this {
215 fn as_mut(&mut self) -> &mut $inner {
216 &mut self.0
217 }
218 }
219 };
220
221 (@impl [$($generic:tt)+] $this:ty => $field:ident : $inner:ty) => {
222 impl <$($generic)+> ::core::convert::AsMut<$inner> for $this {
223 fn as_mut(&mut self) -> &mut $inner {
224 &mut self.$field
225 }
226 }
227 };
228
229 ($this:ident $(<$($generic:ident),+>)? => $inner:ty) => {
230 impl $(<$($generic),+>)? ::core::convert::AsMut<$inner> for $this $(<$($generic),+>)? {
231 fn as_mut(&mut self) -> &mut $inner {
232 &mut self.0
233 }
234 }
235 };
236
237 ($this:ident $(<$($generic:ident),+>)? => $field:ident : $inner:ty) => {
238 impl $(<$($generic),+>)? ::core::convert::AsMut<$inner> for $this $(<$($generic),+>)? {
239 fn as_mut(&mut self) -> &mut $inner {
240 &mut self.$field
241 }
242 }
243 };
244}
245
246#[macro_export]
280macro_rules! forward_as_mut {
281 (<$($generic:ident),+> in $($rest:tt)+) => {
282 $crate::forward_as_mut!(@impl [$($generic),+] $($rest)+);
283 };
284
285 (<const $($rest:tt)+) => {
286 $crate::__impl_more_parse_generics!(@parse forward_as_mut [] [] const $($rest)+);
287 };
288
289 (<$generic:ident, $($rest:tt)+) => {
290 $crate::__impl_more_parse_generics!(@parse forward_as_mut [] [] $generic, $($rest)+);
291 };
292
293 (@impl [$($generic:tt)+] $this:ty => $target:ty) => {
294 impl <$($generic)+> ::core::convert::AsMut<$target> for $this {
295 fn as_mut(&mut self) -> &mut $target {
296 ::core::convert::AsMut::<$target>::as_mut(&mut self.0)
297 }
298 }
299 };
300
301 (@impl [$($generic:tt)+] $this:ty => $field:ident : $target:ty) => {
302 impl <$($generic)+> ::core::convert::AsMut<$target> for $this {
303 fn as_mut(&mut self) -> &mut $target {
304 ::core::convert::AsMut::<$target>::as_mut(&mut self.$field)
305 }
306 }
307 };
308
309 ($this:ty => $target:ty) => {
310 impl ::core::convert::AsMut<$target> for $this {
311 fn as_mut(&mut self) -> &mut $target {
312 ::core::convert::AsMut::<$target>::as_mut(&mut self.0)
313 }
314 }
315 };
316
317 ($this:ty => $field:ident : $target:ty) => {
318 impl ::core::convert::AsMut<$target> for $this {
319 fn as_mut(&mut self) -> &mut $target {
320 ::core::convert::AsMut::<$target>::as_mut(&mut self.$field)
321 }
322 }
323 };
324}
325
326#[macro_export]
357macro_rules! forward_as_ref_and_mut {
358 (<$($generic:ident),+> in $($rest:tt)+) => {
359 $crate::forward_as_ref_and_mut!(@impl [$($generic),+] $($rest)+);
360 };
361
362 (<const $($rest:tt)+) => {
363 $crate::__impl_more_parse_generics!(@parse forward_as_ref_and_mut [] [] const $($rest)+);
364 };
365
366 (<$generic:ident, $($rest:tt)+) => {
367 $crate::__impl_more_parse_generics!(@parse forward_as_ref_and_mut [] [] $generic, $($rest)+);
368 };
369
370 (@impl [$($generic:tt)+] $this:ty => $target:ty) => {
371 $crate::forward_as_ref!(@impl [$($generic)+] $this => $target);
372 $crate::forward_as_mut!(@impl [$($generic)+] $this => $target);
373 };
374
375 (@impl [$($generic:tt)+] $this:ty => $field:ident : $target:ty) => {
376 $crate::forward_as_ref!(@impl [$($generic)+] $this => $field: $target);
377 $crate::forward_as_mut!(@impl [$($generic)+] $this => $field: $target);
378 };
379
380 ($this:ty => $target:ty) => {
381 $crate::forward_as_ref!($this => $target);
382 $crate::forward_as_mut!($this => $target);
383 };
384
385 ($this:ty => $field:ident : $target:ty) => {
386 $crate::forward_as_ref!($this => $field: $target);
387 $crate::forward_as_mut!($this => $field: $target);
388 };
389}
390
391#[cfg(test)]
392mod tests {
393 use alloc::{string::String, vec, vec::Vec};
394
395 struct Newtype(String);
396 forward_as_ref!(Newtype => str);
397 forward_as_mut!(Newtype => str);
398
399 struct Generic<T>(Vec<T>);
400 forward_as_ref!(<T> in Generic<T> => [T]);
401 forward_as_mut!(<T> in Generic<T> => [T]);
402
403 struct GenericNamed<T> {
404 inner: Vec<T>,
405 }
406 forward_as_ref_and_mut!(<T> in GenericNamed<T> => inner: [T]);
407
408 static_assertions::assert_impl_all!(Newtype: AsRef<str>, AsMut<str>);
409 static_assertions::assert_impl_all!(Generic<usize>: AsRef<[usize]>, AsMut<[usize]>);
410 static_assertions::assert_impl_all!(GenericNamed<usize>: AsRef<[usize]>, AsMut<[usize]>);
411
412 #[test]
413 fn forwards_newtype() {
414 let mut value = Newtype("hello".into());
415 AsMut::<str>::as_mut(&mut value).make_ascii_uppercase();
416
417 assert_eq!(AsRef::<str>::as_ref(&value), "HELLO");
418 }
419
420 #[test]
421 fn forwards_generic_newtype() {
422 let mut value = Generic(vec![1, 2, 3]);
423 AsMut::<[usize]>::as_mut(&mut value).reverse();
424
425 assert_eq!(AsRef::<[usize]>::as_ref(&value), &[3, 2, 1]);
426 }
427
428 #[test]
429 fn forwards_generic_named_field() {
430 let mut value = GenericNamed {
431 inner: vec![1, 2, 3],
432 };
433 AsMut::<[usize]>::as_mut(&mut value).reverse();
434
435 assert_eq!(AsRef::<[usize]>::as_ref(&value), &[3, 2, 1]);
436 }
437}