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. Type parameters require special handling, see examples.
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 named field struct and type parameter:
20/// ```
21/// struct MyStruct<T> { msg: T };
22/// impl_more::impl_deref!(<T> in MyStruct<T> => msg: T);
23///
24/// let foo = MyStruct { msg: "two".to_owned() };
25/// assert_eq!(foo.len(), 3);
26/// ```
27///
28/// [`Deref`]: core::ops::Deref
29/// [`impl_deref_mut`]: crate::impl_deref_mut
30/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
31/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
32#[macro_export]
33macro_rules! impl_deref {
34    (<$($generic:ident),+> in $this:ty => $target:ty) => {
35        impl <$($generic),+> ::core::ops::Deref for $this {
36            type Target = $target;
37
38            fn deref(&self) -> &Self::Target {
39                &self.0
40            }
41        }
42    };
43
44    (<$($generic:ident),+> in $this:ty => $field:ident : $target:ty) => {
45        impl <$($generic),+> ::core::ops::Deref for $this {
46            type Target = $target;
47
48            fn deref(&self) -> &Self::Target {
49                &self.$field
50            }
51        }
52    };
53
54    ($this:ty => $target:ty) => {
55        impl ::core::ops::Deref for $this {
56            type Target = $target;
57
58            fn deref(&self) -> &Self::Target {
59                &self.0
60            }
61        }
62    };
63
64    ($this:ty => $field:ident : $target:ty) => {
65        impl ::core::ops::Deref for $this {
66            type Target = $target;
67
68            fn deref(&self) -> &Self::Target {
69                &self.$field
70            }
71        }
72    };
73}
74
75/// Implement [`DerefMut`] for a struct.
76///
77/// The first argument is that of the struct to create the impl for and this type must also
78/// implement [`Deref`]. The second argument is required for non-newtype structs and is the field
79/// to deref to.
80///
81/// This macro has the same type parameter support and format as [`impl_deref`].
82///
83/// Also see [`impl_deref`], [`impl_deref_and_mut`], and [`forward_deref_and_mut`].
84///
85/// # Examples
86/// With a newtype struct:
87/// ```
88/// use impl_more::{impl_deref, impl_deref_mut};
89///
90/// struct Foo(String);
91///
92/// impl_deref!(Foo => String);
93/// impl_deref_mut!(Foo);
94///
95/// let mut foo = Foo("bar".to_owned());
96/// foo.push('!');
97///
98/// assert_eq!(*foo, "bar!");
99/// ```
100///
101/// With a named field struct and type parameter:
102/// ```
103/// struct Foo<T> { msg: T };
104/// impl_more::impl_deref!(<T> in Foo<T> => msg: T);
105/// impl_more::impl_deref_mut!(<T> in Foo<T> => msg);
106///
107/// let mut foo = Foo { msg: "bar".to_owned() };
108/// foo.push('!');
109///
110/// assert_eq!(*foo, "bar!");
111/// ```
112///
113/// [`Deref`]: core::ops::Deref
114/// [`DerefMut`]: core::ops::DerefMut
115/// [`impl_deref`]: crate::impl_deref
116/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
117/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
118#[macro_export]
119macro_rules! impl_deref_mut {
120    (<$($generic:ident),+> in $this:ty) => {
121        impl <$($generic),+> ::core::ops::DerefMut for $this {
122            fn deref_mut(&mut self) -> &mut Self::Target {
123                &mut self.0
124            }
125        }
126    };
127
128    (<$($generic:ident),+> in $this:ty => $field:ident) => {
129        impl <$($generic),+> ::core::ops::DerefMut for $this {
130            fn deref_mut(&mut self) -> &mut Self::Target {
131                &mut self.$field
132            }
133        }
134    };
135
136    ($this:ty) => {
137        impl ::core::ops::DerefMut for $this {
138            fn deref_mut(&mut self) -> &mut Self::Target {
139                &mut self.0
140            }
141        }
142    };
143
144    ($this:ty => $field:ident) => {
145        impl ::core::ops::DerefMut for $this {
146            fn deref_mut(&mut self) -> &mut Self::Target {
147                &mut self.$field
148            }
149        }
150    };
151}
152
153/// Implements [`Deref`] and [`DerefMut`] by forwarding through an inner field's implementation.
154///
155/// Use the `ref <type>` form for deref-ing to types with lifetimes like `&str`. For newtype
156/// structs, only the struct name and deref target type is necessary.
157///
158/// This macro has the same type parameter support and format as [`impl_deref`].
159///
160/// Also see [`forward_deref_and_mut`].
161///
162/// # Examples
163/// ```
164/// struct MyNewTypeStruct(String);
165/// impl_more::impl_deref_and_mut!(MyNewTypeStruct => String);
166///
167/// let foo = MyNewTypeStruct("one".to_owned());
168/// let foo_ref: &String = &foo;
169///
170/// // Unlike `forward_deref_and_mut`, this macro will not forward the deref implementation
171/// // through the named type. Even so, in some cases Rust will be able to support these cases.
172///
173/// let foo_ref: &str = &foo;
174///
175/// fn accepts_string_slice(_: &str) {}
176/// accepts_string_slice(&foo);
177/// ```
178///
179/// [`Deref`]: core::ops::Deref
180/// [`DerefMut`]: core::ops::DerefMut
181/// [`impl_deref`]: crate::impl_deref
182/// [`forward_deref_and_mut`]: crate::forward_deref_and_mut
183#[macro_export]
184macro_rules! impl_deref_and_mut {
185    (<$($generic:ident),+> in $this:ty => $target:ty) => {
186        impl <$($generic),+> ::core::ops::Deref for $this {
187            type Target = $target;
188
189            fn deref(&self) -> &Self::Target {
190                &self.0
191            }
192        }
193
194        impl <$($generic),+> ::core::ops::DerefMut for $this {
195            fn deref_mut(&mut self) -> &mut Self::Target {
196                &mut self.0
197            }
198        }
199    };
200
201    (<$($generic:ident),+> in $this:ty => $field:ident : $target:ty) => {
202        impl <$($generic),+> ::core::ops::Deref for $this {
203            type Target = $target;
204
205            fn deref(&self) -> &Self::Target {
206                &self.$field
207            }
208        }
209
210        impl <$($generic),+> ::core::ops::DerefMut for $this {
211            fn deref_mut(&mut self) -> &mut Self::Target {
212                &mut self.$field
213            }
214        }
215    };
216
217    ($this:ty => $target:ty) => {
218        impl ::core::ops::Deref for $this {
219            type Target = $target;
220
221            fn deref(&self) -> &Self::Target {
222                &self.0
223            }
224        }
225
226        impl ::core::ops::DerefMut for $this {
227            fn deref_mut(&mut self) -> &mut Self::Target {
228                &mut self.0
229            }
230        }
231    };
232
233    ($this:ty => $field:ident : $target:ty) => {
234        impl ::core::ops::Deref for $this {
235            type Target = $target;
236
237            fn deref(&self) -> &Self::Target {
238                &self.$field
239            }
240        }
241
242        impl ::core::ops::DerefMut for $this {
243            fn deref_mut(&mut self) -> &mut Self::Target {
244                &mut self.$field
245            }
246        }
247    };
248}
249
250/// Implements [`Deref`] and [`DerefMut`] by forwarding through an inner field's implementation.
251///
252/// Use the `ref <type>` form for deref-ing to types with lifetimes like `&str`. For newtype
253/// structs, only the struct name and deref target type is necessary.
254///
255/// Also see [`impl_deref_and_mut`].
256///
257/// # Examples
258/// With a newtype struct:
259/// ```
260/// # fn accepts_string_slice(_: &str) {}
261/// # fn accepts_mut_string_slice(_: &mut str) {}
262/// #
263/// struct MyNewTypeStruct(String);
264/// impl_more::forward_deref_and_mut!(MyNewTypeStruct => ref str);
265/// let mut foo = MyNewTypeStruct("one".to_owned());
266/// let foo_ref: &str = &foo;
267/// accepts_string_slice(&foo);
268/// accepts_mut_string_slice(&mut foo);
269/// ```
270///
271/// [`impl_deref_and_mut`]: crate::impl_deref_and_mut
272/// [`Deref`]: core::ops::Deref
273/// [`DerefMut`]: core::ops::DerefMut
274#[macro_export]
275macro_rules! forward_deref_and_mut {
276    ($ty:ty => $target:ty) => {
277        impl ::core::ops::Deref for $ty {
278            type Target = $target;
279
280            fn deref(&self) -> &Self::Target {
281                ::core::ops::Deref::deref(&self.0)
282            }
283        }
284
285        impl ::core::ops::DerefMut for $ty {
286            fn deref_mut(&mut self) -> &mut Self::Target {
287                ::core::ops::DerefMut::deref_mut(&mut self.0)
288            }
289        }
290    };
291
292    ($ty:ty => ref $target:ty) => {
293        impl<'__impl_more_a> ::core::ops::Deref for $ty {
294            type Target = $target;
295
296            fn deref(&self) -> &Self::Target {
297                ::core::ops::Deref::deref(&self.0)
298            }
299        }
300
301        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
302            fn deref_mut(&mut self) -> &mut Self::Target {
303                ::core::ops::DerefMut::deref_mut(&mut self.0)
304            }
305        }
306    };
307
308    ($ty:ty => $field:ident : $target:ty) => {
309        impl ::core::ops::Deref for $ty {
310            type Target = $target;
311
312            fn deref(&self) -> &Self::Target {
313                ::core::ops::Deref::deref(&self.$field)
314            }
315        }
316
317        impl ::core::ops::DerefMut for $ty {
318            fn deref_mut(&mut self) -> &mut Self::Target {
319                ::core::ops::DerefMut::deref_mut(&mut self.$field)
320            }
321        }
322    };
323
324    ($ty:ty => $field:ident : ref $target:ty) => {
325        impl<'__impl_more_a> ::core::ops::Deref for $ty {
326            type Target = $target;
327
328            fn deref(&self) -> &Self::Target {
329                ::core::ops::Deref::deref(&self.$field)
330            }
331        }
332
333        impl<'__impl_more_a> ::core::ops::DerefMut for $ty {
334            fn deref_mut(&mut self) -> &mut Self::Target {
335                ::core::ops::DerefMut::deref_mut(&mut self.$field)
336            }
337        }
338    };
339}
340
341#[cfg(test)]
342mod tests {
343    #![allow(dead_code)]
344
345    use alloc::{borrow::ToOwned as _, string::String};
346    use core::ops::{Deref, DerefMut};
347
348    fn accepts_string_slice(_: &str) {}
349    fn accepts_mut_string_slice(_: &mut str) {}
350
351    struct Foo1(String);
352    impl_deref_and_mut!(Foo1 => String);
353    static_assertions::assert_impl_all!(
354        Foo1:
355        // impls
356        Deref<Target = String>,
357        DerefMut<Target = String>,
358    );
359
360    struct Foo2(String);
361    forward_deref_and_mut!(Foo2 => ref str);
362    static_assertions::assert_impl_all!(
363        Foo2:
364        // impls
365        Deref,
366        DerefMut,
367    );
368
369    struct SingleGeneric<T>(T);
370    impl_deref!(<T> in SingleGeneric<T> => T);
371    impl_deref_mut!(<T> in SingleGeneric<T>);
372    static_assertions::assert_impl_all!(
373        SingleGeneric<usize>:
374        // impls
375        Deref<Target = usize>,
376        DerefMut<Target = usize>,
377    );
378
379    struct SingleGenericCombined<T>(T);
380    impl_deref_and_mut!(<T> in SingleGenericCombined<T> => T);
381    static_assertions::assert_impl_all!(
382        SingleGenericCombined<usize>:
383        // impls
384        Deref<Target = usize>,
385        DerefMut<Target = usize>,
386    );
387
388    struct DoubleGeneric<T, U> {
389        t: T,
390        _u: U,
391    }
392    impl_deref!(<T, U> in DoubleGeneric<T, U> => t: T);
393    impl_deref_mut!(<T, U> in DoubleGeneric<T, U> => t);
394    static_assertions::assert_impl_all!(
395        DoubleGeneric<usize, u32>:
396        // impls
397        Deref<Target = usize>,
398        DerefMut<Target = usize>,
399    );
400
401    struct DoubleGenericCombined<T, U> {
402        t: T,
403        _u: U,
404    }
405    impl_deref_and_mut!(<T, U> in DoubleGenericCombined<T, U> => t: T);
406    static_assertions::assert_impl_all!(
407        DoubleGenericCombined<usize, u32>:
408        // impls
409        Deref<Target = usize>,
410        DerefMut<Target = usize>,
411    );
412
413    #[test]
414    fn foo2_impls() {
415        let mut foo = Foo2("".to_owned());
416        accepts_string_slice(&foo);
417        accepts_mut_string_slice(&mut foo);
418    }
419
420    struct Foo3 {
421        msg: String,
422    }
423    forward_deref_and_mut!(Foo3 => msg: ref str);
424    static_assertions::assert_impl_all!(
425        Foo3:
426        // impls
427        Deref,
428        DerefMut,
429    );
430
431    #[test]
432    fn foo3_impls() {
433        let mut foo = Foo3 { msg: "".to_owned() };
434        accepts_string_slice(&foo);
435        accepts_mut_string_slice(&mut foo);
436    }
437}