Derive Macro core_extensions::TransparentNewtype
source · [−]#[derive(TransparentNewtype)]
{
// Attributes available to this derive:
#[twrap]
}
derive
and transparent_newtype
only.Expand description
Derives the TransparentNewtype
trait.
This derive macro requires the type to be a struct
with a #[repr(transparent)]
representation.
If the type has multiple fields, the derive macro errors when
the non-#[twrap]
-annotated fields don’t ìmplement the MarkerType
trait
(which ensures that those fields are all zero-sized).
For examples look below
Attributes
Container attributes
Attributes used above the type definition.
#[twrap(crate = foo::bar)]
(example):
Replaces the path to core_extensions
with foo::bar
#[twrap(where T: Foo + Bar)]
(example):
Adds arbitrary bounds to the TransparentNewtype
impl.
#[twrap(debug_print)]
:
For diagnostics, causes the derive macro to panic with the code generated by it.
Field attributes
#[twrap]
(example):
Tells the derive macro that this is the wrapped field, and other fields are zero-sized.
#[twrap(delegate)]
(example):
Tells the derive macro to delegate the TransparentNewtype
impl to this field.
This adds a TypeOfThisField: TransparentNewtype
bound to the implementation.
Examples
Single-field struct
use core_extensions::{TransparentNewtype, TransparentNewtypeExt};
#[derive(Debug, PartialEq, TransparentNewtype)]
#[repr(transparent)]
struct SingleField<T>(T);
assert_eq!(SingleField::from_inner(3), SingleField(3));
assert_eq!(SingleField::from_inner_ref(&5), &SingleField(5));
assert_eq!(SingleField::from_inner_mut(&mut 8), &mut SingleField(8));
Many-field struct
use core_extensions::{TransparentNewtype, TransparentNewtypeExt};
use std::marker::PhantomData;
#[derive(Debug, PartialEq, TransparentNewtype)]
#[repr(transparent)]
struct WithPhantom<T, U>{
ghost: PhantomData<U>,
// you need to annotate the wrapped field when this has zero-sized fields.
#[twrap]
value: T,
}
assert_eq!(
WithPhantom::<_, &str>::from_inner(13),
WithPhantom{value: 13, ghost: PhantomData},
);
assert_eq!(
WithPhantom::<_, String>::from_inner_ref(&21),
&WithPhantom{value: 21, ghost: PhantomData},
);
assert_eq!(
WithPhantom::<_, Vec<u8>>::from_inner_mut(&mut 34),
&mut WithPhantom{value: 34, ghost: PhantomData},
);
Delegating to type parameter
This example demonstrates how you can delegate the TransparentNewtype
implementation
to a field.
use core_extensions::{TransparentNewtype, TransparentNewtypeExt};
use std::num::Wrapping;
use std::mem::ManuallyDrop as MD;
#[derive(Debug, PartialEq, TransparentNewtype)]
#[repr(transparent)]
struct Foo<T>(
#[twrap(delegate)]
T,
);
assert_eq!(<Foo<Wrapping<u8>>>::from_inner(13), Foo(Wrapping(13)));
assert_eq!(<Foo<Wrapping<u16>>>::from_inner_ref(&21), &Foo(Wrapping(21)));
assert_eq!(<Foo<Wrapping<u32>>>::from_inner_mut(&mut 34), &mut Foo(Wrapping(34)));
assert_eq!(<Foo<MD<u8>>>::from_inner(55), Foo(MD::new(55)));
assert_eq!(<Foo<MD<u16>>>::from_inner_ref(&89), &Foo(MD::new(89)));
assert_eq!(<Foo<MD<u32>>>::from_inner_mut(&mut 144), &mut Foo(MD::new(144)));
Crate attribute
This example demonstrates how you can use this derive macro when this crate is renamed.
use cext::{TransparentNewtype, TransparentNewtypeExt};
#[derive(Debug, PartialEq, TransparentNewtype)]
#[twrap(crate = cext)]
#[repr(transparent)]
struct SingleField<T>(T);
assert_eq!(SingleField::from_inner(3), SingleField(3));
assert_eq!(SingleField::from_inner_ref(&5), &SingleField(5));
assert_eq!(SingleField::from_inner_mut(&mut 8), &mut SingleField(8));
Additional bounds
This example demonstrates how you can make the TransparentNewtype
impl conditional.
use core_extensions::{TransparentNewtype, TransparentNewtypeExt};
#[derive(Debug, PartialEq, TransparentNewtype)]
#[twrap(where T: Copy)]
#[repr(transparent)]
struct CopyWrapper<T>{
val: T
}
assert_eq!(CopyWrapper::from_inner(3), CopyWrapper{val: 3});
assert_eq!(CopyWrapper::from_inner_ref(&5), &CopyWrapper{val: 5});
assert_eq!(CopyWrapper::from_inner_mut(&mut 8), &mut CopyWrapper{val: 8});
This doesn’t compile because CopyWrapper
requires the wrapped type to be Copy
:
CopyWrapper::from_inner(String::new());