#id #newtype #derive #identifier #pattern #type #integral

macro id-derive

Derive-based newtype pattern for integral IDs in Rust

1 unstable release

0.1.0 Mar 20, 2020

#60 in #newtype

Apache-2.0/MIT

22KB
456 lines

Derive basic integer operations for newtype IDs.

License

id-derive is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.


lib.rs:

The goal of this crate is to provide an easy newtype implementation for different types of strongly-typed identifiers.

Motivation

Very often, I find myself utilizing many integer-based IDs. In effort to make it strongly typed, one typically uses a "newtype" pattern.

struct MyId(usize);

let id = MyId(1);
assert_eq!(id.0, 1);
assert_eq!(MyId(id.0 + 10).0, MyId(11).0);

Notice how you have to access the tuple element with .0 any time you want to perform any type of operations on the actual integer. One could approach this by implementing Deref trait but this is strongly discouraged; see: Rust Docs, API Guidelines.

This crate introduces a set of macros implementing certain operations on an ID.

Examples

In the simplest case, you only need to a single derive Id.

#[derive(Id, Debug, PartialEq, Copy, Clone)]
struct MyId(usize);
// Construct from the inner type.
let mut id = MyId::from(1);
// Construct inner type from `MyId`.
assert_eq!(usize::from(id), 1);
// Display.
assert_eq!(&id.to_string(), "1");
// Add two IDs or inner to ID.
assert_eq!(id + MyId(1), MyId(2));
assert_eq!(id + 1, MyId(2));
id += 1;
id += MyId(1);
assert_eq!(id, MyId(3));
// Subtract
assert_eq!(id - MyId(1), MyId(2));
assert_eq!(id - 1, MyId(2));
id -= 1;
id -= MyId(1);
assert_eq!(id, MyId(1));
// Multiply
assert_eq!(id * MyId(2), MyId(2));
assert_eq!(id * 2, MyId(2));
id *= 2;
id *= MyId(2);
assert_eq!(id, MyId(4));
// Divide
assert_eq!(id / MyId(2), MyId(2));
assert_eq!(id / 2, MyId(2));
id /= 2;
id /= MyId(2);
assert_eq!(id, MyId(1));

Alternatively, you may devine only a subset of available derives:

#[derive(Display, FromInner, IntoInner, Add, AddInner)]
struct MyId(usize);

Dependencies

~1.5MB
~33K SLoC