Crate newtype_derive_2018[][src]

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, etc.

All of these macros are designed to be used with the macro-attr-2018 crate, though they can be used independent of it.

Example

Create a simple integer wrapper with some arithmetic operators:

use macro_attr_2018::macro_attr;
use newtype_derive_2018::*;

macro_attr! {
    #[derive(NewtypeAdd!, NewtypeMul!(i32))]
    pub struct Happy(pub i32);
}

// Let's add some happy little ints.
let a = Happy(6);
let b = Happy(7);
let c = (a + b) * 3;
let d: i32 = c.0;
assert_eq!(d, 39);

Create a “deref-transparent” wrapper around a smart pointer:

use macro_attr_2018::macro_attr;
use newtype_derive_2018::*;

macro_attr! {
    #[derive(NewtypeDeref!, NewtypeDerefMut!)]
    pub struct I32Array(Vec<i32>);
}

let mut arr = I32Array(vec![1, 2, 3]);
assert_eq!(&*arr, &[1, 2, 3]);

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.

All of these macros are named Newtype$Trait.

All these macros support generic newtype structs. By default, no bounds for generic parameters generated. To add constraints, they should wrap macros arguments (if any) within parenthesis, and add where clause after it. For example:


macro_attr! {
    #[derive(NewtypeAdd!(where T: Add<Output=T>))]
    #[derive(NewtypeAdd!((&self, &Self) where T: Add<Output=T>))]
    #[derive(NewtypeSub!((*) where T: Sub<Output=T>))]
    pub struct Dummy<T: Copy>(T);
}

Binary Arithmetic Operators

Each of the binary arithmetic operators accept several deriving forms. To use Add on a struct T as an example:

AttributeGenerated implementation
NewtypeAddimpl Add<T, Output=T> for T
NewtypeAdd(&self)impl<'a> Add<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 of T and &T

The *Assign variants accept zero or one argument only. For example:

AttributeGenerated implementation
NewtypeAddAssignimpl AddAssign<T> for T
NewtypeAddAssign(U)impl Add<U> for T
NewtypeAddAssign(*)Implements for T 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:

AttributeGenerated implementation
NewtypeNegimpl 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. The call is forwarded to the wrapped value’s implementation.

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.

Using Without macro_attr!

Although designed to be used with macro_attr!, all of the macros in this crate can be used without it. The following:

use macro_attr_2018::macro_attr;
use newtype_derive_2018::*;

macro_attr! {
    #[derive(Copy, Clone, Debug, NewtypeAdd!, NewtypeAdd!(f32))]
    pub struct Meters(pub f32);
}

can also be written as

use newtype_derive_2018::*;

#[derive(Copy, Clone, Debug)]
pub struct Meters(pub f32);

NewtypeAdd! { () pub struct Meters(pub f32); }
NewtypeAdd! { (f32) pub struct Meters(pub f32); }

Macros