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/// # Examples
334/// With a newtype struct:
335/// ```
336/// # fn accepts_string_slice(_: &str) {}
337/// # fn accepts_mut_string_slice(_: &mut str) {}
338/// #
339/// struct MyNewTypeStruct(String);
340/// impl_more::forward_deref_and_mut!(MyNewTypeStruct => ref str);
341/// let mut foo = MyNewTypeStruct("one".to_owned());
342/// let foo_ref: &str = &foo;
343/// accepts_string_slice(&foo);
344/// accepts_mut_string_slice(&mut foo);
345/// ```
346///
347/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
348/// [`Deref`]: core::ops::Deref
349/// [`DerefMut`]: core::ops::DerefMut
350#[macro_export]
351macro_rules! forward_deref_and_mut {
352    ($ty:ty => $target:ty) => {
353        impl ::core::ops::Deref for $ty {
354            type Target = $target;
355
356            fn deref(&self) -> &Self::Target {
357                ::core::ops::Deref::deref(&self.0)
358            }
359        }
360
361        impl ::core::ops::DerefMut for $ty {
362            fn deref_mut(&mut self) -> &mut Self::Target {
363                ::core::ops::DerefMut::deref_mut(&mut self.0)
364            }
365        }
366    };
367
368    ($ty:ty => ref $target:ty) => {
369        impl<'__impl_more_a> ::core::ops::Deref for $ty {
370            type Target = $target;
371
372            fn deref(&self) -> &Self::Target {
373                ::core::ops::Deref::deref(&self.0)
374            }
375        }
376
377        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
378            fn deref_mut(&mut self) -> &mut Self::Target {
379                ::core::ops::DerefMut::deref_mut(&mut self.0)
380            }
381        }
382    };
383
384    ($ty:ty => $field:ident : $target:ty) => {
385        impl ::core::ops::Deref for $ty {
386            type Target = $target;
387
388            fn deref(&self) -> &Self::Target {
389                ::core::ops::Deref::deref(&self.$field)
390            }
391        }
392
393        impl ::core::ops::DerefMut for $ty {
394            fn deref_mut(&mut self) -> &mut Self::Target {
395                ::core::ops::DerefMut::deref_mut(&mut self.$field)
396            }
397        }
398    };
399
400    ($ty:ty => $field:ident : ref $target:ty) => {
401        impl<'__impl_more_a> ::core::ops::Deref for $ty {
402            type Target = $target;
403
404            fn deref(&self) -> &Self::Target {
405                ::core::ops::Deref::deref(&self.$field)
406            }
407        }
408
409        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
410            fn deref_mut(&mut self) -> &mut Self::Target {
411                ::core::ops::DerefMut::deref_mut(&mut self.$field)
412            }
413        }
414    };
415}
416
417#[cfg(test)]
418mod tests {
419    #![allow(dead_code)]
420
421    use alloc::{borrow::ToOwned as _, string::String};
422    use core::ops::{Deref, DerefMut};
423
424    fn accepts_string_slice(_: &str) {}
425    fn accepts_mut_string_slice(_: &mut str) {}
426
427    struct Foo1(String);
428    impl_deref_and_mut!(Foo1 => String);
429    static_assertions::assert_impl_all!(
430        Foo1:
431        // impls
432        Deref<Target = String>,
433        DerefMut<Target = String>,
434    );
435
436    struct Foo2(String);
437    forward_deref_and_mut!(Foo2 => ref str);
438    static_assertions::assert_impl_all!(
439        Foo2:
440        // impls
441        Deref,
442        DerefMut,
443    );
444
445    struct SingleGeneric<T>(T);
446    impl_deref!(<T> in SingleGeneric<T> => T);
447    impl_deref_mut!(<T> in SingleGeneric<T>);
448    static_assertions::assert_impl_all!(
449        SingleGeneric<usize>:
450        // impls
451        Deref<Target = usize>,
452        DerefMut<Target = usize>,
453    );
454
455    struct SingleGenericCombined<T>(T);
456    impl_deref_and_mut!(<T> in SingleGenericCombined<T> => T);
457    static_assertions::assert_impl_all!(
458        SingleGenericCombined<usize>:
459        // impls
460        Deref<Target = usize>,
461        DerefMut<Target = usize>,
462    );
463
464    struct DoubleGeneric<T, U> {
465        t: T,
466        _u: U,
467    }
468    impl_deref!(<T, U> in DoubleGeneric<T, U> => t: T);
469    impl_deref_mut!(<T, U> in DoubleGeneric<T, U> => t);
470    static_assertions::assert_impl_all!(
471        DoubleGeneric<usize, u32>:
472        // impls
473        Deref<Target = usize>,
474        DerefMut<Target = usize>,
475    );
476
477    struct DoubleGenericCombined<T, U> {
478        t: T,
479        _u: U,
480    }
481    impl_deref_and_mut!(<T, U> in DoubleGenericCombined<T, U> => t: T);
482    static_assertions::assert_impl_all!(
483        DoubleGenericCombined<usize, u32>:
484        // impls
485        Deref<Target = usize>,
486        DerefMut<Target = usize>,
487    );
488
489    #[test]
490    fn foo2_impls() {
491        let mut foo = Foo2("".to_owned());
492        accepts_string_slice(&foo);
493        accepts_mut_string_slice(&mut foo);
494    }
495
496    struct Foo3 {
497        msg: String,
498    }
499    forward_deref_and_mut!(Foo3 => msg: ref str);
500    static_assertions::assert_impl_all!(
501        Foo3:
502        // impls
503        Deref,
504        DerefMut,
505    );
506
507    #[test]
508    fn foo3_impls() {
509        let mut foo = Foo3 { msg: "".to_owned() };
510        accepts_string_slice(&foo);
511        accepts_mut_string_slice(&mut foo);
512    }
513}