snowcloud/
lib.rs

1//! # Snowcloud
2//!
3//! a small library for implementing custom ids based on timestamps, static
4//! ids, and sequence counters. the module provides 2 types of generators, a
5//! thread safe and non thread safe version. they allow for different types of
6//! waiting for ids if you want specific behavior. each generator is capable of
7//! using different snowflake types to allow for different snowflake formats.
8//!
9//! examples of using snowflakes with `i64` base types
10//!
11//! ```rust
12//! // 43 bit timestamp, 8 bit primary id, 12 bit sequence
13//! type MyFlake = snowcloud::i64::SingleIdFlake<43, 8, 12>;
14//! type MyCloud = snowcloud::Generator<MyFlake>;
15//!
16//! // 2023/03/23 9:00:00 in milliseconds, timestamps will start from this
17//! // date
18//! const START_TIME: u64 = 1679587200000;
19//!
20//! let mut cloud = MyCloud::new(START_TIME, 1)
21//!     .expect("failed to create MyCloud");
22//! let flake = cloud.next_id()
23//!     .expect("failed to create snowflake");
24//!
25//! println!("{}", flake.id());
26//! ```
27//!
28//! creating a snowflake with two id segments
29//!
30//! ```rust
31//! // 43 bit timestamp, 4 bit primary id, 4 bit secondary id, 12 bit sequence
32//! type MyFlake = snowcloud::i64::DualIdFlake<43, 4, 4, 12>;
33//! type MyCloud = snowcloud::Generator<MyFlake>;
34//!
35//! // 2023/03/23 9:00:00 in milliseconds, timestamps will start from this
36//! // date
37//! const START_TIME: u64 = 1679587200000;
38//!
39//! let mut cloud = MyCloud::new(START_TIME, (1, 1))
40//!     .expect("failed to create MyCloud");
41//! let flake = cloud.next_id()
42//!     .expect("failed to create snowflake");
43//!
44//! println!("{}", flake.id());
45//! ```
46//!
47//! ## Behavior
48//!
49//! [`sync::MutexGenerator`] is a thread safe implementation for sharing
50//! between threads on a system. it uses an [`Arc`](std::sync::Arc)
51//! [`Mutex`](std::sync::Mutex) to handle sharing the sequence count and
52//! prev_time. the only time it will block is when acquiring the mutex and will
53//! not wait if a valid snowflake cannot be acquired. if a generator is unable
54//! to create a snowflake because the max sequence number has been reached an
55//! error will be returned providing an estimated duration to the next 
56//! millisecond. how you want to wait can be decided by the user.
57//!
58//! [`Generator`] is similar in most aspects to `sync::MutexGenerator` expect 
59//! next_id is a mutating call and sequence count with prev_time are not stored
60//! in an Arc Mutext. THIS IS NOT THREAD SAFE.
61//!
62//! ## Traits
63//!
64//! to help with using a generator in other situations, traits are provided and
65//! implemented for the base types (more can be added later if
66//! necessary/desired).
67//!
68//! - [`IdGenerator`](crate::traits::IdGenerator) describes the basic layout of
69//!   an id generator. requiring an Error, Id, and Output type to be specified
70//!   along with the next_id method.
71//! - [`IdGeneratorMut`](crate::traits::IdGeneratorMut) is similar to
72//!   [`IdGenerator`](crate::traits::IdGenerator) except the next_id call
73//!   allows for mutating the object
74//! - [`NextAvailId`](crate::traits::NextAvailId) describes an object that is
75//!   capable of returing a [`duraiton`](std::time::Duration) to the next 
76//!   available millisecond. check 
77//!   [`blocking_next_id`](crate::wait::blocking_next_id) for example 
78//!   implementation.
79//! - [`Id`](crate::traits::Id) describes base methods for what an Id requires.
80//!   currently just handles turning a snowflake into its base type like an
81//!   `i64`.
82//!
83//! ## Timestamps
84//!
85//! all snowflakes use timestamps of milliseconds with the generators using
86//! [`SystemTime`](std::time::SystemTime) to track the provided epoch and
87//! generate new timestamps for snowflakes. the start date must be in the 
88//! future of [`UNIX_EPOCH`](std::time::SystemTime::UNIX_EPOCH) and cannot be a
89//! date in the future, `now >= start_time >= UNIX_EPOCH`.
90//!
91//! ```rust
92//! // the current example date is 2023/03/23 9:00:00.
93//! const VALID_START_DATE: u64 =   1679587200000;
94//!
95//! // if a date that is after the current system time is provided the
96//! // snowcloud will return an error. 2077/10/23 9:00:00
97//! const INVALID_START_DATE: u64 = 3402205200000;
98//! ```
99//!
100//! below is a table with various bit values and how many years you can get out
101//! of a timestamp. you will probably get diminishing returns with lower bit
102//! values if this is to be used over a long duration of time.
103//!
104//! | bits | max value | years |
105//! | ---: | --------: | ----: |
106//! | 43 | 8796093022207 | 278 |
107//! | 42 | 4398046511103 | 139 |
108//! | 41 | 2199023255551 | 69 |
109//! | 40 | 1099511627775 | 34 |
110//! | 39 | 549755813887 | 17 |
111//! | 38 | 274877906943 | 8 |
112//! | 37 | 137438953471 | 4 |
113//! | 36 | 68719476735 | 2 |
114//! | 35 | 34359738367 | 1 |
115//!
116//! ## De/Serialize
117//!
118//! snowflakes support serde [`Serialize`](serde::Serialize) and
119//! [`Deserialize`](serde::Deserialize) to there internal types with an 
120//! addtional option to de/serailize to a string. see 
121//! [`serde_ext`](crate::serde_ext) for additional methods of de/serialization
122
123pub mod traits;
124mod error;
125
126#[cfg(feature = "serde")]
127pub mod serde_ext;
128
129mod flake;
130mod cloud;
131
132pub mod wait;
133
134pub use error::Error;
135pub use flake::*;
136pub use cloud::*;