pavo_traits/
wrap.rs

1//! 类型包装类契定。
2//!
3
4/// 定义内部类型拷贝契定。
5pub trait InnerCopy<T> {
6    /// 返回内部类型拷贝。
7    fn inner(&self) -> T;
8}
9
10/// 定义内部类型引用契定。
11pub trait InnerRefer<T> {
12    /// 返回内部类型引用。
13    fn inner(&self) -> &T;
14
15    /// 返回内部类型可变引用。
16    fn inner_mut(&mut self) -> &mut T;
17}
18
19/// 实现包装枚举两者之间的 [From] 特性。
20///
21/// [From]: https://doc.rust-lang.org/std/convert/trait.From.html
22///
23/// # Examples
24///
25/// ```
26/// use pavo_traits::{impl_from_between_enum};
27///
28/// mod ffi {
29///     // The enum in ffi with C style.
30///     #[repr(u32)]
31///     #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
32///     pub enum MODE_E {
33///         MODE_E_A,
34///         MODE_E_B,
35///         MODE_E_C,
36///     }
37///
38///     // The API of argumented with MODE_E.
39///     pub fn set_mode(mode: MODE_E) -> MODE_E {
40///         mode
41///     }
42/// }
43///
44/// // The enum wrapped with Rust style.
45/// #[repr(u32)]
46/// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
47/// pub enum Mode {
48///     A,
49///     B,
50///     C,
51/// }
52///
53/// // impl From<ffi::MODE_E> for Mode and From<Mode> for ffi::MODE_E.
54/// impl_from_between_enum!(Mode, ffi::MODE_E);
55///
56/// // Use from/into to convert the types.
57/// assert_eq!(Mode::from(ffi::set_mode(Mode::A.into())), Mode::A);
58/// ```
59#[macro_export]
60macro_rules! impl_from_between_enum {
61    ($Wrapper:ty, $Inner:ty) => {
62        impl From<$Inner> for $Wrapper {
63            fn from(val: $Inner) -> Self {
64                unsafe { std::mem::transmute::<$Inner, Self>(val) }
65            }
66        }
67
68        impl From<$Wrapper> for $Inner {
69            fn from(val: $Wrapper) -> Self {
70                unsafe { std::mem::transmute::<$Wrapper, Self>(val) }
71            }
72        }
73    };
74}
75
76/// 实现包装枚举的 [From] 及 [Into] 特性。
77///
78/// [From]: https://doc.rust-lang.org/std/convert/trait.From.html
79/// [Into]: https://doc.rust-lang.org/std/convert/trait.Into.html
80///
81/// # Examples
82///
83/// ```
84/// use pavo_traits::{impl_from_into_for_enum};
85///
86/// mod ffi {
87///     // The enum in ffi with C style.
88///     #[repr(u32)]
89///     #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
90///     pub enum MODE_E {
91///         MODE_E_A,
92///         MODE_E_B,
93///         MODE_E_C,
94///     }
95///
96///     // The API of argumented with MODE_E.
97///     pub fn set_mode(mode: MODE_E) -> MODE_E {
98///         mode
99///     }
100/// }
101///
102/// // The enum wrapped with Rust style.
103/// #[repr(u32)]
104/// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
105/// pub enum Mode {
106///     A,
107///     B,
108///     C,
109/// }
110///
111/// // impl From<ffi::MODE_E>/Into<ffi::MODE_E> for Mode.
112/// impl_from_into_for_enum!(Mode, ffi::MODE_E);
113///
114/// // Use from/into to convert the types.
115/// assert_eq!(Mode::from(ffi::set_mode(Mode::A.into())), Mode::A);
116/// ```
117#[macro_export]
118macro_rules! impl_from_into_for_enum {
119    ($Wrapper:ty, $Inner:ty) => {
120        impl From<$Inner> for $Wrapper {
121            fn from(val: $Inner) -> Self {
122                unsafe { std::mem::transmute::<$Inner, Self>(val) }
123            }
124        }
125
126        impl Into<$Inner> for $Wrapper {
127            fn into(self) -> $Inner {
128                unsafe { std::mem::transmute::<Self, $Inner>(self) }
129            }
130        }
131    };
132}
133
134/// 实现包装结构两者之间的 [From] 契定。
135///
136/// [From]: https://doc.rust-lang.org/std/convert/trait.From.html
137///
138/// # Examples
139///
140/// ```
141/// use pavo_traits::{impl_from_between_struct};
142///
143/// mod ffi {
144///     // The struct in ffi with C style.
145///     #[repr(C)]
146///     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd)]
147///     pub struct DATA_S {
148///         a: usize,
149///         b: usize,
150///         c: usize,
151///         d: usize,
152///     }
153///
154///     // The API of argumented with DATA_S.
155///     pub fn set_data(data: &DATA_S) -> DATA_S {
156///         *data
157///     }
158/// }
159///
160/// // The struct wrapped with Rust style.
161/// #[repr(C)]
162/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
163/// pub struct Data {
164///     inner: ffi::DATA_S,
165/// }
166///
167/// // impl From<ffi::DATA_S> for Data and From<Data> for ffi::DATA_S.
168/// impl_from_between_struct!(Data, ffi::DATA_S);
169///
170/// impl Data {
171///     fn new() -> Self {
172///         Self { inner: Default::default() }
173///     }
174/// }
175///
176/// // Use from/into to convert the types.
177/// let d = Data::new();
178/// assert_eq!(Data::from(ffi::set_data(&d.into())), d);
179/// ```
180#[macro_export]
181macro_rules! impl_from_between_struct {
182    ($Wrapper:ty, $Inner:ty) => {
183        impl From<$Inner> for $Wrapper {
184            fn from(val: $Inner) -> Self {
185                Self { inner: val }
186            }
187        }
188
189        impl From<$Wrapper> for $Inner {
190            fn from(val: $Wrapper) -> Self {
191                val.inner
192            }
193        }
194    };
195}
196
197/// 实现包装结构的 [From] 及 [Into] 契定。
198///
199/// [From]: https://doc.rust-lang.org/std/convert/trait.From.html
200/// [Into]: https://doc.rust-lang.org/std/convert/trait.Into.html
201///
202/// # Examples
203///
204/// ```
205/// use pavo_traits::{impl_from_into_for_struct};
206///
207/// mod ffi {
208///     // The struct in ffi with C style.
209///     #[repr(C)]
210///     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd)]
211///     pub struct DATA_S {
212///         a: usize,
213///         b: usize,
214///         c: usize,
215///         d: usize,
216///     }
217///
218///     // The API of argumented with DATA_S.
219///     pub fn set_data(data: &DATA_S) -> DATA_S {
220///         *data
221///     }
222/// }
223///
224/// // The struct wrapped with Rust style.
225/// #[repr(C)]
226/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
227/// pub struct Data {
228///     inner: ffi::DATA_S,
229/// }
230///
231/// // impl From<ffi::DATA_S>/Into<ffi::DATA_S> for Data.
232/// impl_from_into_for_struct!(Data, ffi::DATA_S);
233///
234/// impl Data {
235///     fn new() -> Self {
236///         Self { inner: Default::default() }
237///     }
238/// }
239///
240/// // Use from/into to convert the types.
241/// let d = Data::new();
242/// assert_eq!(Data::from(ffi::set_data(&d.into())), d);
243/// ```
244#[macro_export]
245macro_rules! impl_from_into_for_struct {
246    ($Wrapper:ty, $Inner:ty) => {
247        impl From<$Inner> for $Wrapper {
248            fn from(val: $Inner) -> Self {
249                Self { inner: val }
250            }
251        }
252
253        impl Into<$Inner> for $Wrapper {
254            fn into(self) -> $Inner {
255                self.inner
256            }
257        }
258    };
259}
260
261/// 实现包装类型的 [InnerCopy] 契定。
262///
263/// [InnerCopy]: trait.InnerCopy.html
264///
265/// # Examples
266///
267/// ```
268/// use pavo_traits::{impl_inner_copy, InnerCopy};
269///
270/// #[derive(Clone, Copy)]
271/// struct Bar {}
272///
273/// struct Foo {
274///    inner: Bar,
275/// }
276///
277/// impl_inner_copy!(Foo, Bar);
278/// ```
279#[macro_export]
280macro_rules! impl_inner_copy {
281    ($Wrapper:ty, $Inner:ty) => {
282        impl InnerCopy<$Inner> for $Wrapper {
283            fn inner(&self) -> $Inner {
284                self.inner
285            }
286        }
287    };
288}
289
290/// 实现包装类型的 [InnerRefer] 契定。
291///
292/// [InnerRefer]: trait.InnerRefer.html
293///
294/// # Examples
295///
296/// ```
297/// use pavo_traits::{impl_inner_refer, InnerRefer};
298///
299/// struct Bar {}
300///
301/// struct Foo {
302///    inner: Bar,
303/// }
304///
305/// impl_inner_refer!(Foo, Bar);
306/// ```
307#[macro_export]
308macro_rules! impl_inner_refer {
309    ($Wrapper:ty, $Inner:ty) => {
310        impl InnerRefer<$Inner> for $Wrapper {
311            fn inner(&self) -> &$Inner {
312                &self.inner
313            }
314
315            fn inner_mut(&mut self) -> &mut $Inner {
316                &mut self.inner
317            }
318        }
319    };
320}
321
322/// 实现包装结构的通用契定。
323/// 包括:[AsRef], [AsPtr], [AsPtrMut], [InnerRefer]。
324///
325/// [AsRef]: https://doc.rust-lang.org/std/convert/trait.AsRef.html
326/// [AsPtr]: trait.AsPtr.html
327/// [AsPtrMut]: trait.AsPtrMut.html
328/// [InnerRefer]: trait.InnerRefer.html
329///
330/// # Examples
331///
332/// ```
333/// use pavo_traits::{impl_struct_wrapper, AsPtr, AsPtrMut, InnerRefer};
334///
335/// #[derive(Clone, Copy, Debug)]
336/// struct Bar {}
337///
338/// #[derive(Debug)]
339/// struct Foo {
340///    inner: Bar,
341/// }
342///
343/// impl_struct_wrapper!(Foo, Bar);
344///
345/// let f = Foo { inner: Bar {} };
346/// assert_eq!(std::ptr::eq(f.as_ref(), &f.inner), true);
347/// assert_eq!(std::ptr::eq(f.as_ref(), f.inner()), true);
348/// assert_eq!(std::ptr::eq(f.inner(), &f.inner), true);
349/// ```
350#[macro_export(local_inner_macros)]
351macro_rules! impl_struct_wrapper {
352    ($Wrapper:ty, $Inner:ty) => {
353        impl_as_mut_and_ref!($Wrapper);
354        impl_as_ref!($Wrapper, $Inner, inner);
355        impl_as_mut!($Wrapper, $Inner, inner);
356        // impl_as_ptr!($Wrapper, $Inner);
357        // impl_as_ptr_mut!($Wrapper, $Inner);
358        impl_from_between_struct!($Wrapper, $Inner);
359        impl_inner_refer!($Wrapper, $Inner);
360    };
361}
362
363#[cfg(test)]
364mod tests {
365    use super::*;
366    use std::sync::Arc;
367
368    #[repr(C)]
369    #[derive(Debug)]
370    struct FooCopy {
371        inner: usize,
372    }
373
374    impl_inner_copy!(FooCopy, usize);
375
376    #[test]
377    fn test_inner_copy() {
378        let f = FooCopy { inner: 123 };
379        let v = f.inner();
380        assert_eq!(v, f.inner);
381    }
382
383    #[repr(C)]
384    #[derive(Debug)]
385    struct FooRefer {
386        inner: Arc<usize>,
387    }
388
389    impl_inner_refer!(FooRefer, Arc<usize>);
390
391    #[test]
392    fn test_inner_refer() {
393        let mut f = FooRefer {
394            inner: Arc::new(123),
395        };
396        assert_eq!(&**f.inner(), &123usize);
397        assert_eq!(std::ptr::eq(f.inner(), &f.inner), true);
398        *Arc::make_mut(f.inner_mut()) = 456;
399        assert_eq!(&**f.inner(), &456usize);
400    }
401}