wrapper

Macro wrapper 

Source
macro_rules! wrapper {
    (
        @INTERNAL IMPL
        #[wrapper_impl(AsRef)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(AsMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(ConstAsMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(Borrow)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(BorrowMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(Deref)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(DerefMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(From)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(Debug)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        #[wrapper_impl(DebugName)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL IMPL
        $(#[$outer:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? ($inner_vis:vis $inner_ty:ty) $(;)?
    ) => { ... };
    (
        @INTERNAL 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
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL 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
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(AsRef)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(AsMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(ConstAsMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(Borrow)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(BorrowMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(Debug)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(DebugName)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(DerefMut)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(Deref)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL
        #[wrapper_impl(From)]
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_AS_REF
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_AS_MUT
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_CONST_AS_MUT
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_CONST_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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_BORROW
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_BORROW_MUT
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_BORROW_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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_DEBUG
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_DEBUG_NAME
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_DEREF_MUT
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_DEREF
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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)?
            )*
            $(,)?
        }
    ) => { ... };
    (
        @INTERNAL WRAPPER_IMPL_FROM
        $(#[$meta:meta])*
        $vis:vis struct $name:ident$(<$($lt:tt$(:$clt:tt$(+$dlt:tt)*)?),+>)? $(;)?
        ($inner_vis:vis $inner_ty:ty)
        $($tt:tt)*
    ) => { ... };
    (
        @INTERNAL 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
            )*
            $(,)?
        }
    ) => { ... };
    (@INTERNAL WRAPPER_IMPL_FROM $($tt:tt)*) => { ... };
    (@INTERNAL WRAPPER_IMPL $($tt:tt)*) => { ... };
    (@INTERNAL $($tt:tt)*) => { ... };
    ($($tt:tt)*) => { ... };
}
Expand description

Helper macro for creating a wrapper over any type (new-type idiom).

§Usage

It’s worth noting that wrapper! { ... } is almost equivalent to wrapper!( ... ); but lacking cargo-fmt support. We recommend using the latter.

§Usage: basic

wrapper_lite::wrapper!(
    #[wrapper_impl(AsRef)]
    #[wrapper_impl(AsMut)]
    // #[wrapper_impl(Borrow)]
    #[wrapper_impl(BorrowMut)]
    // #[wrapper_impl(Deref)]
    #[wrapper_impl(DerefMut)]
    #[wrapper_impl(From)]
    #[derive(Debug, Clone, Copy)]
    pub struct 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 too complex, or you need some custom fields.

Here’s an complex example:

wrapper_lite::wrapper!(
    #[wrapper_impl(AsMut)]
    #[wrapper_impl(AsRef)]
    // #[wrapper_impl(Borrow)]
    #[wrapper_impl(BorrowMut)]
    //     #[wrapper_impl(Deref)]
    #[wrapper_impl(DerefMut)]
    #[wrapper_impl(From)]
    #[wrapper_impl(Debug)]
    #[derive(Clone, Copy, PartialEq, Eq)]
    #[repr(transparent)]
    pub struct ExampleWrapperComplex<'a, 'b, P> {
        inner: P,
        _a: ::core::marker::PhantomData<&'a ()>,
        _b: ::core::marker::PhantomData<&'b ()>,
    }
);

There’re some limitations:

  • The inner field must be named as inner.
  • When no default value is specified, the wrapper type will not implement the From trait. Will also not generate the const_from method.
  • 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 the Debug trait if the inner type implements it. The debug output is the same as the inner one.
  • #[wrapper_impl(DebugName)]: implements the Debug trait, but only prints the name of the wrapper type.
wrapper_lite::wrapper!(
    #[wrapper_impl(Debug)]
    #[derive(Clone, Copy)]
    pub struct ExampleWrapperDebug<'a, P>(&'a P);
);

wrapper_lite::wrapper!(
    #[wrapper_impl(DebugName)]
    #[derive(Clone, Copy)]
    pub struct 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"
);

§ConstAsMut

Like AsMut, but instead generates a const version of as_inner_mut method (stable since Rust 1.83.0+).

wrapper_lite::wrapper!(
    #[wrapper_impl(ConstAsMut)]
    #[derive(Debug, Clone, Copy)]
    pub struct ExampleWrapper<P>(pub(crate) P);
);

const fn const_fn_example<P>(w: &mut ExampleWrapper<P>) -> &mut P {
    w.as_inner_mut()
}

§Notes

  • The wrapper_impl attribute must be on top of any other attributes.

  • For BorrowMut and DerefMut, the macro will automatically implement the corresponding Borrow and Deref traits, so the following two examples will fail to compile:

    wrapper_lite::wrapper!(
        #[wrapper_impl(Borrow)]
        #[wrapper_impl(BorrowMut)]
        pub struct ExampleWrapper<P>(pub(crate) P);
    );
    wrapper_lite::wrapper!(
        #[wrapper_impl(Deref)]
        #[wrapper_impl(DerefMut)]
        pub struct ExampleWrapper<P>(pub(crate) P);
    );