Expand description
This crate provides several macros for deriving implementations of various traits for “newtype” wrappers (i.e. tuple structs with a single element). That is, given a tuple struct with exactly one field (e.g. struct Buckets(i32)
), these macros will derive “obvious” implementations of traits such as Add
, Neg
, Index
, Deref
, From
, etc.
All of these macros are designed to be used with the custom_derive
crate, though they can be used independent of it.
§Example
Create a simple integer wrapper with some arithmetic operators:
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;
custom_derive! {
#[derive(NewtypeFrom, NewtypeAdd, NewtypeMul(i32))]
pub struct Happy(i32);
}
// Let's add some happy little ints.
let a = Happy::from(6);
let b = Happy::from(7);
let c = (a + b) * 3;
let d: i32 = c.into();
assert_eq!(d, 39);
Create a “deref-transparent” wrapper around a type:
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate newtype_derive;
custom_derive! {
#[derive(NewtypeFrom,
NewtypeDeref, NewtypeDerefMut,
NewtypeIndex(usize), NewtypeIndexMut(usize)
)]
pub struct I32Array(Vec<i32>);
}
let mut arr = I32Array::from(vec![1, 2, 3]);
arr.push(4);
arr[2] = 5;
assert_eq!(&**arr, &[1, 2, 5, 4]);
assert_eq!(arr.len(), 4);
§Overview
This crate provides macros to derive implementations of the following traits for newtype structs:
- Binary Arithmetic Operators: Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Sub, Shl, Shr, plus the corresponding *Assign traits.
- Unary Arithmetic Operators: Neg, Not.
- Other Operators: Deref, DerefMut, Index, IndexMut.
- Formatting: Binary, Debug, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex.
- Miscellaneous: From.
- Unstable: One, Product, Sum, Zero (requires the
std-unstable
feature).
All of these macros are named Newtype$Trait
.
None of these macros currently support generic newtype structs.
§Binary Arithmetic Operators
Each of the binary arithmetic operators accept several deriving forms. To use Add
on a struct T
as an example:
NewtypeAdd
:impl Add<T, Output=T> for T
NewtypeAdd(&self)
:impl<'a> Add<&'a T, Output=T> for &'a T
NewtypeAdd(U)
:impl Add<U, Output=T> for T
NewtypeAdd(&self, U)
:impl<'a> Add<U, Output=T> for &'a T
NewtypeAdd(*)
: All four combinations ofT
and&T
The *Assign
variants accept zero or one argument only. For example:
NewtypeAddAssign
:impl AddAssign<T> for T
NewtypeAddAssign(&Self)
:impl<'a> Add<&'a T> for &'a T
NewtypeAddAssign(U)
:impl Add<U> for T
NewtypeAddAssign(*)
: Implements forT
and&T
.
In all cases, the implementation unwraps the newtype (where necessary), forwards to the wrapped value’s implementation, then re-wraps the result in the newtype.
§Unary Arithmetic Operators
Each of the binary arithmetic operators accept several deriving forms. To use Neg
on a struct T
as an example:
NewtypeNeg
:impl Neg<Output=T> for T
NewtypeNeg(&self)
:impl<'a> Neg<Output=T> for &'a T
NewtypeNeg(*)
: both of the above
In all cases, the implementation unwraps the newtype, forwards to the wrapped value’s implementation, then re-wraps the result in the newtype.
§Other Operators
NewtypeDeref
and NewtypeDerefMut
only support the argument-less form, and implements the corresponding trait such that the newtype structure derefs to a pointer to the wrapped value.
NewtypeIndex
and NewtypeIndexMut
must be used as NewtypeIndex(usize)
, where the argument is the type to use for indexing. The call is forwarded to the wrapped value’s implementation.
§Formatting
The deriving macros for the formatting traits in std::fmt
forward to the wrapped value’s implementation.
§Miscellaneous
NewtypeFrom
implements std::convert::From
twice: once for converting from the wrapped type to the newtype, and once for converting from the newtype to the wrapped type.
NewtypeProduct
and NewtypeSum
optionally support specifying &Self
as an argument to generate an implementation that accepts an iterator of borrowed pointers (e.g. NewtypeSum(&Self)
).
§Using Without custom_derive!
Although designed to be used with custom_derive!
, all of the macros in this crate can be used without it. The following:
custom_derive! {
#[derive(Copy, Clone, Debug, NewtypeFrom, NewtypeAdd, NewtypeAdd(f32))]
pub struct Meters(f32);
}
Can also be written as:
#[derive(Copy, Clone, Debug)]
pub struct Meters(f32);
NewtypeFrom! { () pub struct Meters(f32); }
NewtypeAdd! { () pub struct Meters(f32); }
NewtypeAdd! { (f32) pub struct Meters(f32); }