# Newtypes
The `newtypes` crate is meant to ease the implementation of the
[Newtype](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html)
pattern while trying to make as few assumptions as possible.
## Layout guarantee
Every type produced by every macro in this crate is annotated with
[`#[repr(transparent)]`](https://doc.rust-lang.org/reference/type-layout.html#the-transparent-representation),
so its size and alignment match the inner type's. This is a stable part of
the crate's contract and will not be removed.
## `newtype!` Macro
The `newtype!` macro creates a barebones newtype by wrapping an inner type with
a struct, and, if possible, implementing some extra traits for it.
By default, all declared structs have visibility `pub`.
```rust
use newtypes::newtype;
newtype!(NewTypeName, underlying_type);
// In case we want to automatically derive traits (like serde's
// Serialize or Deserialize):
newtype!(NewTypeName, underlying_type; Trait1, ..., TraitN);
```
Example:
```rust
use newtypes::newtype;
use serde::{Deserialize, Serialize}
newtype!(UserId, u32);
newtype!(GroupId, u32; Serialize, Deserialize);
```
### Implemented traits
- For all:
- [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html)
- [`Into<inner_type>`](https://doc.rust-lang.org/std/convert/trait.Into.html)
- For integers:
- [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
- [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)
- [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html)
- [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
- [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html)
- For floating point numbers:
- [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
- [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)
- [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
- For `String`:
- [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
- [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html)
- [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
- [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html)
> **IMPORTANT:** The inner value is private. If there are no constraints on the
> inner value, then we can rely on [`newtype_from!`](#newtype_from-macro) macro
> to implement the `From` and `FromStr` traits for us.
>
> Otherwise we can choose to implement
> [`From`](https://doc.rust-lang.org/std/convert/trait.From.html),
> [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) and
> [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html)
> manually.
## `newtype_ord!` Macro
The `newtype_ord!` macro extends the functionality provided with
[`newtype!`](#newtype-macro) by implementing the
[`PartialOrd`](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) and
[`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) traits
(when possible).
Example:
```rust
use newtypes::newtype_ord;
use serde::{Deserialize, Serialize}
newtype_ord!(Rank, u16);
newtype_ord!(TicketNumber, u16; Serialize, Deserialize);
```
> **NOTE:** It only works for integers, floating point numbers, and `String`.
## `newtype_unit!` Macro
The `newtype_unit!` macro extends the functionality provided with
[`newtype_ord!`](#newtype_ord-macro) by implementing the
[`Add`](https://doc.rust-lang.org/std/ops/trait.Add.html),
[`Sub`](https://doc.rust-lang.org/std/ops/trait.Sub.html),
[`AddAssign`](https://doc.rust-lang.org/std/ops/trait.AddAssign.html),
[`SubAssign`](https://doc.rust-lang.org/std/ops/trait.SubAssign.html), and
[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) traits.
Example:
```rust
use newtypes::newtype_unit;
use serde::Deserialize;
newtype_unit!(Weight, f32);
newtype_unit!(Length, f32; Deserialize);
```
> **NOTE:** It only works for integers and floating point numbers.
> **NOTE:** It does not implement arithmetic operations beyond addition and
> subtraction. Doing that properly would require a more complex library focused
> on dealing with "units" (example: multiplying lengths gives us an area).
## `newtype_struct!` Macro
The `newtype_struct!` macro creates a newtype that wraps a user-defined struct
(or any non-scalar inner type), implementing
[`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html),
[`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html),
[`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html), and
[`Into<inner_type>`](https://doc.rust-lang.org/std/convert/trait.Into.html).
The inner type must itself implement `Debug + Clone + PartialEq`. Extra traits
(`Copy`, `Hash`, `Eq`, `Ord`, `PartialOrd`, `Serialize`, …) can be requested by
passing them after the `;` separator and will be derived on the generated
struct.
Example:
```rust
use newtypes::newtype_struct;
#[derive(Debug, Clone, PartialEq)]
pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32 }
newtype_struct!(Vertex, Vec3);
```
With extra derives:
```rust
use newtypes::newtype_struct;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32 }
newtype_struct!(Vertex, Vec3; Serialize, Deserialize);
```
## `newtype_array!` Macro
The `newtype_array!` macro creates a newtype that wraps a fixed-size array
`[T; N]` and exposes array-like ergonomics:
[`Index`](https://doc.rust-lang.org/std/ops/trait.Index.html) /
[`IndexMut`](https://doc.rust-lang.org/std/ops/trait.IndexMut.html) (covering
`usize` and every range kind via
[`SliceIndex<[T]>`](https://doc.rust-lang.org/std/slice/trait.SliceIndex.html)),
[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)
for `Self`, `&Self`, and `&mut Self`, inherent `len`, `is_empty`, `iter`,
`iter_mut`, `as_array`, `as_array_mut`, plus `AsRef<[T]>`, `AsMut<[T]>`, and
`Into<[T; N]>`.
`Deref<Target = [T]>` is **not** emitted by default — see
[`newtype_array_deref!`](#newtype_array_deref-macro) for the variant that adds
it.
Default trait derives depend on the element type:
- Integers (`i8`..`i128`, `u8`..`u128`, `isize`, `usize`):
`Debug, Clone, Copy, PartialEq, Eq, Hash`
- Floats (`f32`, `f64`): `Debug, Clone, Copy, PartialEq`
- `String`: `Debug, Clone, PartialEq, Eq, Hash`
- Any other element type: `Debug, Clone, PartialEq` (the inner type must
itself implement these)
Extra derives can be requested after `;`:
```rust
use newtypes::newtype_array;
newtype_array!(MacAddr, u8, 6);
let m = MacAddr([0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe]);
assert_eq!(0xde, m[0]);
assert_eq!(6, m.len());
let _slice: &[u8] = &m[1..3];
```
With extra derives:
```rust
use newtypes::newtype_array;
use serde::{Deserialize, Serialize};
newtype_array!(MacAddr, u8, 6; Serialize, Deserialize);
```
> **NOTE:** `From<[T; N]>` is not emitted by default. Pair with
> [`newtype_from_only!`](#newtype_from_only-macro) if implicit construction
> from an array is desired.
## `newtype_array_deref!` Macro
The `newtype_array_deref!` macro behaves exactly like
[`newtype_array!`](#newtype_array-macro) but additionally implements
[`Deref<Target = [T]>`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
and
[`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html).
This exposes every slice method (`first`, `last`, `contains`, `fill`,
`chunks`, `windows`, `split`, …) directly on the newtype and lets `&Name`
coerce to `&[T]` implicitly. The convenience comes at the cost of partially
erasing the wrapper at call sites, which can defeat the type-safety
motivation of the newtype pattern. Prefer
[`newtype_array!`](#newtype_array-macro) unless you specifically want the
full slice surface.
```rust
use newtypes::newtype_array_deref;
newtype_array_deref!(Buf, u8, 4);
let b = Buf([1, 2, 3, 4]);
assert_eq!(Some(&1u8), b.first());
assert_eq!(Some(&4u8), b.last());
assert!(b.contains(&3));
```
## `newtype_validated!` Macro
The `newtype_validated!` macro creates a newtype whose constructor enforces an
invariant. Validation always runs; there is no `unsafe` escape hatch. Invalid
values yield an error.
The error type is generated alongside the newtype as a zero-sized struct
implementing `Debug + Clone + Copy + PartialEq + Eq + Display + Error`. Its
name must be supplied explicitly because `macro_rules!` cannot synthesise
`{Name}Error` on stable Rust without third-party dependencies.
`From<inner>` is **not** emitted (it would bypass validation).
[`TryFrom<inner>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) is
emitted and delegates to `Self::new`.
The validator can be either a closure or a free-function path; both must be
callable as `Fn(&inner) -> bool`.
Example:
```rust
use newtypes::newtype_validated;
newtype_validated!(Probability, ProbabilityError, f32, |x: &f32| (0.0..=1.0).contains(x));
assert!(Probability::new(0.5).is_ok());
assert!(Probability::new(2.0).is_err());
```
With a free function:
```rust
use newtypes::newtype_validated;
fn is_even(x: &u32) -> bool { x % 2 == 0 }
newtype_validated!(EvenU32, EvenU32Error, u32, is_even);
```
> **WARNING:** Validation runs only at construction time. Wrapping a type with
> interior mutability (e.g. `RefCell`, `Cell`) defeats the invariant because
> the inner value can mutate after construction.
> **WARNING:** Combining `newtype_validated!` with `newtype_from!` (or
> `newtype_from_only!`) on the same newtype emits `From<inner>` and silently
> bypasses validation.
## `newtype_from!` Macro
The macro `newtype_from!` implements the `From` and `FromStr` traits for us
in case it's possible.
It has to be used in combination with one of the other ones
([`newtype!`](#newtype-macro), [`newtype_ord!`](#newtype_ord-macro), or
[`newtype_unit!`](#newtype_unit-macro)).
Example:
```rust
use newtypes::{newtype, newtype_from};
newtype!(Weight, f32);
newtype_from!(Weight, f32);
```
> **NOTE:** It only works for integers, floating point numbers, and `String`.
## `newtype_from_only!` Macro
The macro `newtype_from_only!` implements only the `From` trait, leaving
`FromStr` to the caller. Use it when a type should be constructible from its
inner value but should not parse from text.
Example:
```rust
use newtypes::{newtype, newtype_from_only};
newtype!(VertexIndex, u32);
newtype_from_only!(VertexIndex, u32);
```
> **NOTE:** It works for integers, floating point numbers, `String`, and
> arbitrary inner types.
## `newtype_fromstr!` Macro
The macro `newtype_fromstr!` implements only the `FromStr` trait, leaving
`From<inner>` to the caller. Use it when a type should parse from text but
should not be implicitly constructible from its inner value.
Example:
```rust
use newtypes::{newtype, newtype_fromstr};
use std::str::FromStr;
newtype!(Age, u8);
newtype_fromstr!(Age, u8);
let a = Age::from_str("42").unwrap();
```
> **NOTE:** It only works for integers, floating point numbers, and `String`.
> For arbitrary inner types implement `FromStr` manually.