macro_rules! wrapper {
(
@INTERNEL IMPL
#[wrapper_impl(AsRef)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(AsMut)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(Borrow)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(Deref)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(DerefMut)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(From)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(Debug)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
#[wrapper_impl(DebugName)]
$($tt:tt)*
) => { ... };
(
@INTERNEL IMPL
$(#[$outer:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? ($inner_vis:vis $inner_ty:ty) $(;)?
) => { ... };
(
@INTERNEL IMPL
$(#[$outer:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty = $field_default: expr
)*
$(,)?
}
) => { ... };
(
@INTERNEL IMPL
$(#[$outer:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(AsRef)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(AsMut)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(Borrow)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(Debug)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(DebugName)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(DerefMut)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(Deref)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL
#[wrapper_impl(From)]
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_AS_REF
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_AS_REF
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_AS_MUT
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_AS_MUT
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_BORROW
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_BORROW
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEBUG
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEBUG
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEBUG_NAME
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEBUG_NAME
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEREF_MUT
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEREF_MUT
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEREF
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_DEREF
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty$( = $field_default: expr)?
)*
$(,)?
}
) => { ... };
(
@INTERNEL WRAPPER_IMPL_FROM
$(#[$meta:meta])*
$vis:vis $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
($inner_vis:vis $inner_ty:ty)
$($tt:tt)*
) => { ... };
(
@INTERNEL WRAPPER_IMPL_FROM
$(#[$meta:meta])*
$vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? {
$(#[$field_inner_meta:meta])*
$inner_vis:vis inner: $inner_ty:ty
$(
,
$(#[$field_meta:meta])*
$field_vis:vis $field:ident: $field_ty:ty = $field_default:expr
)*
$(,)?
}
) => { ... };
(@INTERNEL WRAPPER_IMPL_FROM $($tt:tt)*) => { ... };
(@INTERNEL WRAPPER_IMPL $($tt:tt)*) => { ... };
(@INTERNEL $($tt:tt)*) => { ... };
($($tt:tt)*) => { ... };
}Expand description
Helper macro for creating a wrapper over any type (new-type idom).
§Usage: basic
wrapper! {
#[wrapper_impl(AsRef)]
#[wrapper_impl(AsMut)]
#[wrapper_impl(Borrow)]
// #[wrapper_impl(Deref)]
#[wrapper_impl(DerefMut)]
#[wrapper_impl(From)]
#[derive(Debug, Clone, Copy)]
pub ExampleWrapper<'a, P>(pub(crate) &'a P)
}Generates const accessor methods for wrapper types implementing AsRef and
AsMut traits.
For types implementing AsRef, this creates a const method as_inner that
returns a reference to the wrapped value. For types implementing AsMut,
this creates a const method as_inner_mut that returns a mutable reference
to the wrapped value.
Additionally generates a const constructor method const_from for the
wrapper type, using the same visibility as the inner field. When the From
trait is implemented, also generates a public const method from.
§Usage: advanced
You can also create a wrapper type with a struct with multiple fields, especially when some lifetime markers or generics markers are needed.
wrapper! {
#[wrapper_impl(AsMut)]
#[wrapper_impl(AsRef)]
#[wrapper_impl(Borrow)]
#[wrapper_impl(DerefMut)]
#[wrapper_impl(From)]
#[derive(Debug)]
#[repr(transparent)]
pub struct ExampleWrapperComplex<'a, 'b, P> {
inner: P,
_a: ::core::marker::PhantomData<&'a ()> = ::core::marker::PhantomData,
_b: ::core::marker::PhantomData<&'b ()> = ::core::marker::PhantomData
}
}There’re some limitations:
- The inner field must be named as
inner(e.g.inner: P). - When no default value is specified, the wrapper type will not implement
the
Fromtrait. - Does NOT automatically apply
repr(transparent)attribute, since the macro doesn’t know if other fields were zero-sized types (ZST).
§Special attributes
§Debug and DebugName
We offer Debug and DebugName attributes to control how the wrapper type
is printed when using the Debug trait, instead of #[derive(Debug)].
#[wrapper_impl(Debug)]: transparently implements theDebugtrait if the inner type implements it. The debug output is the same as the inner one.#[wrapper_impl(DebugName)]: implements theDebugtrait, but only prints the name of the wrapper type.
wrapper! {
#[wrapper_impl(Debug)]
#[derive(Clone, Copy)]
pub ExampleWrapperDebug<'a, P>(&'a P)
}
wrapper! {
#[wrapper_impl(DebugName)]
#[derive(Clone, Copy)]
pub ExampleWrapperDebugName<'a, P>(&'a P)
}
let data = "Hello".to_string();
// Here we transparently print the debug output of the inner type.
assert_eq!(
format!("{:?}", ExampleWrapperDebug { inner: &data }),
"\"Hello\""
);
// Here we only print the name of the wrapper type.
assert_eq!(
format!("{:?}", ExampleWrapperDebugName { inner: &data }),
"ExampleWrapperDebugName"
);§Notice
- The
wrapper_implattribute must be on top of any other attributes. - Should NOT implement
DerefandDerefMutat the same time (whenDerefMutis implemented,Derefwould be implemented, too).