Skip to main content

impl_more/
deref.rs

1/// Implement [`Deref`] for a struct.
2///
3/// The first argument is that of the newtype struct to create the impl for and the second is the
4/// deref target type. The third argument is required for non-newtype structs and is the name of the
5/// field to deref to. Declare type and const parameters before `in`, as shown below.
6///
7/// Also see [`impl_deref_mut`], [`impl_deref_and_mut`], and [`forward_deref_and_mut`].
8///
9/// # Examples
10/// With a newtype struct:
11/// ```
12/// struct Foo(String);
13/// impl_more::impl_deref!(Foo => String);
14///
15/// let mut foo = Foo("bar".to_owned());
16/// assert_eq!(foo.len(), 3);
17/// ```
18///
19/// With a type parameter and const parameter:
20/// ```
21/// struct Array<T, const N: usize>([T; N]);
22/// impl_more::impl_deref!(<T, const N: usize> in Array<T, N> => [T; N]);
23///
24/// let array = Array([1, 2, 3]);
25/// assert_eq!(array.len(), 3);
26/// ```
27///
28/// With a named field struct and type parameter:
29/// ```
30/// struct MyStruct<T> { msg: T };
31/// impl_more::impl_deref!(<T> in MyStruct<T> => msg: T);
32///
33/// let foo = MyStruct { msg: "two".to_owned() };
34/// assert_eq!(foo.len(), 3);
35/// ```
36///
37/// [`Deref`]: core::ops::Deref
38/// [`impl_deref_mut`]: crate::impl_deref_mut
39/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
40/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
41#[macro_export]
42macro_rules! impl_deref {
43    (<$($generic:ident),+> in $($rest:tt)+) => {
44        $crate::impl_deref!(@impl [$($generic),+] $($rest)+);
45    };
46
47    (<const $($rest:tt)+) => {
48        $crate::impl_deref!(@parse impl_deref [const] $($rest)+);
49    };
50
51    (<$generic:ident, $($rest:tt)+) => {
52        $crate::impl_deref!(@parse impl_deref [$generic,] $($rest)+);
53    };
54
55    (@parse $macro:ident [$($generic:tt)*] > in $($rest:tt)+) => {
56        $crate::$macro!(@impl [$($generic)*] $($rest)+);
57    };
58
59    (@parse $macro:ident [$($generic:tt)*] $next:tt $($rest:tt)+) => {
60        $crate::impl_deref!(@parse $macro [$($generic)* $next] $($rest)+);
61    };
62
63    (@impl [$($generic:tt)+] $this:ty => $target:ty) => {
64        impl <$($generic)+> ::core::ops::Deref for $this {
65            type Target = $target;
66
67            fn deref(&self) -> &Self::Target {
68                &self.0
69            }
70        }
71    };
72
73    (@impl [$($generic:tt)+] $this:ty => $field:ident : $target:ty) => {
74        impl <$($generic)+> ::core::ops::Deref for $this {
75            type Target = $target;
76
77            fn deref(&self) -> &Self::Target {
78                &self.$field
79            }
80        }
81    };
82
83    ($this:ty => $target:ty) => {
84        impl ::core::ops::Deref for $this {
85            type Target = $target;
86
87            fn deref(&self) -> &Self::Target {
88                &self.0
89            }
90        }
91    };
92
93    ($this:ty => $field:ident : $target:ty) => {
94        impl ::core::ops::Deref for $this {
95            type Target = $target;
96
97            fn deref(&self) -> &Self::Target {
98                &self.$field
99            }
100        }
101    };
102}
103
104/// Implement [`DerefMut`] for a struct.
105///
106/// The first argument is that of the struct to create the impl for and this type must also
107/// implement [`Deref`]. The second argument is required for non-newtype structs and is the field
108/// to deref to.
109///
110/// This macro has the same type and const parameter support and format as [`impl_deref`].
111///
112/// Also see [`impl_deref`], [`impl_deref_and_mut`], and [`forward_deref_and_mut`].
113///
114/// # Examples
115/// With a newtype struct:
116/// ```
117/// use impl_more::{impl_deref, impl_deref_mut};
118///
119/// struct Foo(String);
120///
121/// impl_deref!(Foo => String);
122/// impl_deref_mut!(Foo);
123///
124/// let mut foo = Foo("bar".to_owned());
125/// foo.push('!');
126///
127/// assert_eq!(*foo, "bar!");
128/// ```
129///
130/// With a type parameter and const parameter:
131/// ```
132/// struct Array<T, const N: usize>([T; N]);
133/// impl_more::impl_deref!(<T, const N: usize> in Array<T, N> => [T; N]);
134/// impl_more::impl_deref_mut!(<T, const N: usize> in Array<T, N>);
135///
136/// let mut array = Array([1, 2, 3]);
137/// array[0] = 4;
138///
139/// assert_eq!(*array, [4, 2, 3]);
140/// ```
141///
142/// With a named field struct and type parameter:
143/// ```
144/// struct Foo<T> { msg: T };
145/// impl_more::impl_deref!(<T> in Foo<T> => msg: T);
146/// impl_more::impl_deref_mut!(<T> in Foo<T> => msg);
147///
148/// let mut foo = Foo { msg: "bar".to_owned() };
149/// foo.push('!');
150///
151/// assert_eq!(*foo, "bar!");
152/// ```
153///
154/// [`Deref`]: core::ops::Deref
155/// [`DerefMut`]: core::ops::DerefMut
156/// [`impl_deref`]: crate::impl_deref
157/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
158/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
159#[macro_export]
160macro_rules! impl_deref_mut {
161    (<$($generic:ident),+> in $($rest:tt)+) => {
162        $crate::impl_deref_mut!(@impl [$($generic),+] $($rest)+);
163    };
164
165    (<const $($rest:tt)+) => {
166        $crate::impl_deref!(@parse impl_deref_mut [const] $($rest)+);
167    };
168
169    (<$generic:ident, $($rest:tt)+) => {
170        $crate::impl_deref!(@parse impl_deref_mut [$generic,] $($rest)+);
171    };
172
173    (@impl [$($generic:tt)+] $this:ty) => {
174        impl <$($generic)+> ::core::ops::DerefMut for $this {
175            fn deref_mut(&mut self) -> &mut Self::Target {
176                &mut self.0
177            }
178        }
179    };
180
181    (@impl [$($generic:tt)+] $this:ty => $field:ident) => {
182        impl <$($generic)+> ::core::ops::DerefMut for $this {
183            fn deref_mut(&mut self) -> &mut Self::Target {
184                &mut self.$field
185            }
186        }
187    };
188
189    ($this:ty) => {
190        impl ::core::ops::DerefMut for $this {
191            fn deref_mut(&mut self) -> &mut Self::Target {
192                &mut self.0
193            }
194        }
195    };
196
197    ($this:ty => $field:ident) => {
198        impl ::core::ops::DerefMut for $this {
199            fn deref_mut(&mut self) -> &mut Self::Target {
200                &mut self.$field
201            }
202        }
203    };
204}
205
206/// Implements [`Deref`] and [`DerefMut`] by forwarding through an inner field's implementation.
207///
208/// Use the `ref <type>` form for deref-ing to types with lifetimes like `&str`. For newtype
209/// structs, only the struct name and deref target type is necessary.
210///
211/// This macro has the same type and const parameter support and format as [`impl_deref`].
212///
213/// Also see [`forward_deref_and_mut`].
214///
215/// # Examples
216/// ```
217/// struct MyNewTypeStruct(String);
218/// impl_more::impl_deref_and_mut!(MyNewTypeStruct => String);
219///
220/// let foo = MyNewTypeStruct("one".to_owned());
221/// let foo_ref: &String = &foo;
222///
223/// // Unlike `forward_deref_and_mut`, this macro will not forward the deref implementation
224/// // through the named type. Even so, in some cases Rust will be able to support these cases.
225///
226/// let foo_ref: &str = &foo;
227///
228/// fn accepts_string_slice(_: &str) {}
229/// accepts_string_slice(&foo);
230/// ```
231///
232/// With a type parameter and const parameter:
233/// ```
234/// struct Array<T, const N: usize>([T; N]);
235/// impl_more::impl_deref_and_mut!(<T, const N: usize> in Array<T, N> => [T; N]);
236///
237/// let mut array = Array([1, 2, 3]);
238/// array.reverse();
239///
240/// assert_eq!(*array, [3, 2, 1]);
241/// ```
242///
243/// [`Deref`]: core::ops::Deref
244/// [`DerefMut`]: core::ops::DerefMut
245/// [`impl_deref`]: crate::impl_deref
246/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
247#[macro_export]
248macro_rules! impl_deref_and_mut {
249    (<$($generic:ident),+> in $($rest:tt)+) => {
250        $crate::impl_deref_and_mut!(@impl [$($generic),+] $($rest)+);
251    };
252
253    (<const $($rest:tt)+) => {
254        $crate::impl_deref!(@parse impl_deref_and_mut [const] $($rest)+);
255    };
256
257    (<$generic:ident, $($rest:tt)+) => {
258        $crate::impl_deref!(@parse impl_deref_and_mut [$generic,] $($rest)+);
259    };
260
261    (@impl [$($generic:tt)+] $this:ty => $target:ty) => {
262        impl <$($generic)+> ::core::ops::Deref for $this {
263            type Target = $target;
264
265            fn deref(&self) -> &Self::Target {
266                &self.0
267            }
268        }
269
270        impl <$($generic)+> ::core::ops::DerefMut for $this {
271            fn deref_mut(&mut self) -> &mut Self::Target {
272                &mut self.0
273            }
274        }
275    };
276
277    (@impl [$($generic:tt)+] $this:ty => $field:ident : $target:ty) => {
278        impl <$($generic)+> ::core::ops::Deref for $this {
279            type Target = $target;
280
281            fn deref(&self) -> &Self::Target {
282                &self.$field
283            }
284        }
285
286        impl <$($generic)+> ::core::ops::DerefMut for $this {
287            fn deref_mut(&mut self) -> &mut Self::Target {
288                &mut self.$field
289            }
290        }
291    };
292
293    ($this:ty => $target:ty) => {
294        impl ::core::ops::Deref for $this {
295            type Target = $target;
296
297            fn deref(&self) -> &Self::Target {
298                &self.0
299            }
300        }
301
302        impl ::core::ops::DerefMut for $this {
303            fn deref_mut(&mut self) -> &mut Self::Target {
304                &mut self.0
305            }
306        }
307    };
308
309    ($this:ty => $field:ident : $target:ty) => {
310        impl ::core::ops::Deref for $this {
311            type Target = $target;
312
313            fn deref(&self) -> &Self::Target {
314                &self.$field
315            }
316        }
317
318        impl ::core::ops::DerefMut for $this {
319            fn deref_mut(&mut self) -> &mut Self::Target {
320                &mut self.$field
321            }
322        }
323    };
324}
325
326/// Implements [`Deref`] and [`DerefMut`] by forwarding through an inner field's implementation.
327///
328/// Use the `ref <type>` form for deref-ing to types with lifetimes like `&str`. For newtype
329/// structs, only the struct name and deref target type is necessary.
330///
331/// Also see [`impl_deref_and_mut`].
332///
333/// Declare type and const parameters before `in`.
334///
335/// # Examples
336/// With a newtype struct:
337/// ```
338/// # fn accepts_string_slice(_: &str) {}
339/// # fn accepts_mut_string_slice(_: &mut str) {}
340/// #
341/// struct MyNewTypeStruct(String);
342/// impl_more::forward_deref_and_mut!(MyNewTypeStruct => ref str);
343/// let mut foo = MyNewTypeStruct("one".to_owned());
344/// let foo_ref: &str = &foo;
345/// accepts_string_slice(&foo);
346/// accepts_mut_string_slice(&mut foo);
347/// ```
348///
349/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
350/// [`Deref`]: core::ops::Deref
351/// [`DerefMut`]: core::ops::DerefMut
352///
353/// With type and const parameters:
354/// ```
355/// struct Array<T, const N: usize>(Box<[T; N]>);
356/// impl_more::forward_deref_and_mut!(<T, const N: usize> in Array<T, N> => [T; N]);
357///
358/// let mut value = Array(Box::new([1, 2, 3]));
359/// value.reverse();
360/// assert_eq!(*value, [3, 2, 1]);
361/// ```
362#[macro_export]
363macro_rules! forward_deref_and_mut {
364    (<$($generic:ident),+> in $($rest:tt)+) => {
365        $crate::forward_deref_and_mut!(@impl [$($generic),+] $($rest)+);
366    };
367
368    (<const $($rest:tt)+) => {
369        $crate::__impl_more_parse_generics!(@parse forward_deref_and_mut [] [] const $($rest)+);
370    };
371
372    (<$generic:ident, $($rest:tt)+) => {
373        $crate::__impl_more_parse_generics!(@parse forward_deref_and_mut [] [] $generic, $($rest)+);
374    };
375
376    (@impl [$($generic:tt)+] $ty:ty => $target:ty) => {
377        impl <$($generic)+> ::core::ops::Deref for $ty {
378            type Target = $target;
379
380            fn deref(&self) -> &Self::Target {
381                ::core::ops::Deref::deref(&self.0)
382            }
383        }
384
385        impl <$($generic)+> ::core::ops::DerefMut for $ty {
386            fn deref_mut(&mut self) -> &mut Self::Target {
387                ::core::ops::DerefMut::deref_mut(&mut self.0)
388            }
389        }
390    };
391
392    (@impl [$($generic:tt)+] $ty:ty => ref $target:ty) => {
393        impl<'__impl_more_a, $($generic)+> ::core::ops::Deref for $ty {
394            type Target = $target;
395
396            fn deref(&self) -> &Self::Target {
397                ::core::ops::Deref::deref(&self.0)
398            }
399        }
400
401        impl<'__impl_more_a, $($generic)+> ::core::ops::DerefMut for $ty {
402            fn deref_mut(&mut self) -> &mut Self::Target {
403                ::core::ops::DerefMut::deref_mut(&mut self.0)
404            }
405        }
406    };
407
408    (@impl [$($generic:tt)+] $ty:ty => $field:ident : $target:ty) => {
409        impl <$($generic)+> ::core::ops::Deref for $ty {
410            type Target = $target;
411
412            fn deref(&self) -> &Self::Target {
413                ::core::ops::Deref::deref(&self.$field)
414            }
415        }
416
417        impl <$($generic)+> ::core::ops::DerefMut for $ty {
418            fn deref_mut(&mut self) -> &mut Self::Target {
419                ::core::ops::DerefMut::deref_mut(&mut self.$field)
420            }
421        }
422    };
423
424    (@impl [$($generic:tt)+] $ty:ty => $field:ident : ref $target:ty) => {
425        impl<'__impl_more_a, $($generic)+> ::core::ops::Deref for $ty {
426            type Target = $target;
427
428            fn deref(&self) -> &Self::Target {
429                ::core::ops::Deref::deref(&self.$field)
430            }
431        }
432
433        impl<'__impl_more_a, $($generic)+> ::core::ops::DerefMut for $ty {
434            fn deref_mut(&mut self) -> &mut Self::Target {
435                ::core::ops::DerefMut::deref_mut(&mut self.$field)
436            }
437        }
438    };
439
440    ($ty:ty => $target:ty) => {
441        impl ::core::ops::Deref for $ty {
442            type Target = $target;
443
444            fn deref(&self) -> &Self::Target {
445                ::core::ops::Deref::deref(&self.0)
446            }
447        }
448
449        impl ::core::ops::DerefMut for $ty {
450            fn deref_mut(&mut self) -> &mut Self::Target {
451                ::core::ops::DerefMut::deref_mut(&mut self.0)
452            }
453        }
454    };
455
456    ($ty:ty => ref $target:ty) => {
457        impl<'__impl_more_a> ::core::ops::Deref for $ty {
458            type Target = $target;
459
460            fn deref(&self) -> &Self::Target {
461                ::core::ops::Deref::deref(&self.0)
462            }
463        }
464
465        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
466            fn deref_mut(&mut self) -> &mut Self::Target {
467                ::core::ops::DerefMut::deref_mut(&mut self.0)
468            }
469        }
470    };
471
472    ($ty:ty => $field:ident : $target:ty) => {
473        impl ::core::ops::Deref for $ty {
474            type Target = $target;
475
476            fn deref(&self) -> &Self::Target {
477                ::core::ops::Deref::deref(&self.$field)
478            }
479        }
480
481        impl ::core::ops::DerefMut for $ty {
482            fn deref_mut(&mut self) -> &mut Self::Target {
483                ::core::ops::DerefMut::deref_mut(&mut self.$field)
484            }
485        }
486    };
487
488    ($ty:ty => $field:ident : ref $target:ty) => {
489        impl<'__impl_more_a> ::core::ops::Deref for $ty {
490            type Target = $target;
491
492            fn deref(&self) -> &Self::Target {
493                ::core::ops::Deref::deref(&self.$field)
494            }
495        }
496
497        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
498            fn deref_mut(&mut self) -> &mut Self::Target {
499                ::core::ops::DerefMut::deref_mut(&mut self.$field)
500            }
501        }
502    };
503}
504
505#[cfg(test)]
506mod tests {
507    #![allow(dead_code)]
508
509    use alloc::{borrow::ToOwned as _, string::String};
510    use core::ops::{Deref, DerefMut};
511
512    fn accepts_string_slice(_: &str) {}
513    fn accepts_mut_string_slice(_: &mut str) {}
514
515    struct Foo1(String);
516    impl_deref_and_mut!(Foo1 => String);
517    static_assertions::assert_impl_all!(
518        Foo1:
519        // impls
520        Deref<Target = String>,
521        DerefMut<Target = String>,
522    );
523
524    struct Foo2(String);
525    forward_deref_and_mut!(Foo2 => ref str);
526    static_assertions::assert_impl_all!(
527        Foo2:
528        // impls
529        Deref,
530        DerefMut,
531    );
532
533    struct SingleGeneric<T>(T);
534    impl_deref!(<T> in SingleGeneric<T> => T);
535    impl_deref_mut!(<T> in SingleGeneric<T>);
536    static_assertions::assert_impl_all!(
537        SingleGeneric<usize>:
538        // impls
539        Deref<Target = usize>,
540        DerefMut<Target = usize>,
541    );
542
543    struct SingleGenericCombined<T>(T);
544    impl_deref_and_mut!(<T> in SingleGenericCombined<T> => T);
545    static_assertions::assert_impl_all!(
546        SingleGenericCombined<usize>:
547        // impls
548        Deref<Target = usize>,
549        DerefMut<Target = usize>,
550    );
551
552    struct DoubleGeneric<T, U> {
553        t: T,
554        _u: U,
555    }
556    impl_deref!(<T, U> in DoubleGeneric<T, U> => t: T);
557    impl_deref_mut!(<T, U> in DoubleGeneric<T, U> => t);
558    static_assertions::assert_impl_all!(
559        DoubleGeneric<usize, u32>:
560        // impls
561        Deref<Target = usize>,
562        DerefMut<Target = usize>,
563    );
564
565    struct DoubleGenericCombined<T, U> {
566        t: T,
567        _u: U,
568    }
569    impl_deref_and_mut!(<T, U> in DoubleGenericCombined<T, U> => t: T);
570    static_assertions::assert_impl_all!(
571        DoubleGenericCombined<usize, u32>:
572        // impls
573        Deref<Target = usize>,
574        DerefMut<Target = usize>,
575    );
576
577    #[test]
578    fn foo2_impls() {
579        let mut foo = Foo2("".to_owned());
580        accepts_string_slice(&foo);
581        accepts_mut_string_slice(&mut foo);
582    }
583
584    struct Foo3 {
585        msg: String,
586    }
587    forward_deref_and_mut!(Foo3 => msg: ref str);
588    static_assertions::assert_impl_all!(
589        Foo3:
590        // impls
591        Deref,
592        DerefMut,
593    );
594
595    #[test]
596    fn foo3_impls() {
597        let mut foo = Foo3 { msg: "".to_owned() };
598        accepts_string_slice(&foo);
599        accepts_mut_string_slice(&mut foo);
600    }
601}