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;