serial_int/
lib.rs

1/*!
2Serial (or auto-increment) integers make great unique identifers. They do
3not need to be large (i.e. using more memory) to prevent collisions and they
4are always unique until they reach their max value, mimicking the behavior
5of PostgreSQL's `SERIAL` data type. Creating serial values has minimal
6performance impact because it relies on simple adding rather than hashing or
7randomizing.
8
9This crate provides a generator (that is also an iterator) that outputs
10serial values. By default, any unsigned integer from the standard library
11can be generated. This is essentially a counter, a simple iterator for
12integers. This crate is appropriately tiny.
13
14For safety and stability, the generator "saturates" the values instead of
15overflowing. This guarantees that the output values are unique to that
16generator (except for the greatest possible value, e.g. u8::MAX or
17u32::MAX).
18
19# Panics
20
21None
22
23# Examples
24
25A simple example.
26
27```rust
28# use serial_int::SerialGenerator;
29#
30let mut gen = SerialGenerator::<u32>::new();
31
32assert_eq!(0, gen.generate());
33assert_eq!(1, gen.generate());
34```
35
36## Using the "serde_impl" feature
37
38Serialize a generator with Serde.
39
40```rust
41# use serial_int::SerialGenerator;
42# use toml;
43#
44let mut gen = SerialGenerator::<u8>::new();
45
46gen.generate();
47gen.generate();
48
49let gen_string = toml::to_string(&gen).unwrap();
50
51assert_eq!("value = 2\n", gen_string);
52```
53
54Deserialize a generator with Serde.
55
56```rust
57# use serial_int::SerialGenerator;
58# use toml;
59#
60let gen = SerialGenerator::<u8>::new();
61let gen_from_toml =
62    toml::from_str::<SerialGenerator<u8>>("value = 0\n").unwrap();
63
64assert_eq!(gen_from_toml, gen);
65```
66
67## Using `no_std`
68
69No feature flags are needed.
70
71```rust
72#![no_std]
73# use serial_int::SerialGenerator;
74
75fn main() {
76    let mut gen = SerialGenerator::<u8>::new();
77    let serial_ids = [gen.generate(), gen.generate()];
78
79    assert_eq!([0, 1], serial_ids);
80}
81```
82
83## Other
84
85A complex example showing the use of `static` and concurrency
86
87```rust
88# use std::{sync::{Arc, Mutex, OnceLock}, thread};
89# use serial_int::*;
90static ID_GENERATOR: OnceLock<Mutex<SerialGenerator<u64>>> = OnceLock::new();
91
92fn generate_id() -> u64 {
93    ID_GENERATOR
94        .get_or_init(|| Mutex::new(SerialGenerator::new()))
95        .lock()
96        .expect("A thread panicked while trying to generate an ID.")
97        .generate()
98}
99
100struct User {
101    id: u64,
102    email: String,
103}
104
105impl User {
106    pub fn new(email: &str) -> Self {
107        User {
108            id: generate_id(),
109            email: email.to_string(),
110        }
111    }
112}
113
114fn main() {
115    let users_mutex = Arc::new(Mutex::new(Vec::new()));
116    let users_clone = Arc::clone(&users_mutex);
117
118    let handle = thread::spawn(move || {
119        let alice = User::new("alice@domain.xyz");
120        let mary = User::new("mary@domain.xyz");
121        let mut users = users_clone.lock().unwrap();
122
123        users.push(alice);
124        users.push(mary);
125    });
126
127    handle.join().unwrap();
128
129    let bob = User::new("bob@domain.xyz");
130    let fred = User::new("fred@domain.xyz");
131    let mut users = users_mutex.lock().unwrap();
132
133    users.push(bob);
134    users.push(fred);
135
136    assert_eq!(0, users[0].id);
137    assert_eq!(1, users[1].id);
138    assert_eq!(2, users[2].id);
139    assert_eq!(3, users[3].id);
140}
141```
142*/
143
144#![warn(missing_docs)]
145
146mod serial;
147mod serial_generator;
148mod tests;
149
150pub use serial::Serial;
151pub use serial_generator::SerialGenerator;