pub struct TinyId { /* private fields */ }
Expand description
A tiny 8-byte ID type that is NOT cryptographically secure, but is easy and convenient for tasks that don’t require the utmost security or uniqueness. During lightweight testing, between 1 and 10 million IDs can be generated without any collisions, and performance has been pretty good.
Implementations§
source§impl TinyId
impl TinyId
sourcepub const LETTER_COUNT: usize = 64usize
pub const LETTER_COUNT: usize = 64usize
The number of letters that make up the potential pool of characters for a TinyId
.
sourcepub const NULL_DATA: [u8; 8] = _
pub const NULL_DATA: [u8; 8] = _
An instance of a fully null byte array, used as the basis for null ids.
sourcepub const fn is_valid_byte(byte: u8) -> bool
pub const fn is_valid_byte(byte: u8) -> bool
Test whether the given byte is valid for use as one of the 8 bytes in a TinyId
.
This function exists because I’m tired of writing if LETTERS.contains(&byte)
everywhere.
Hopefully it is also more efficient to do it this way.
Letters (as u8):
[45, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
87, 88, 89, 90, 95, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115,
116, 117, 118, 119, 120, 121, 122]
aka
[45, 48..=57, 65..=90, 95, 97..=122]
sourcepub fn null() -> Self
pub fn null() -> Self
Create an instance of the null
TinyId
.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn random() -> Self
pub fn random() -> Self
Create a new random TinyId
.
Examples found in repository?
More examples
42 43 44 45 46 47 48 49 50 51 52 53
fn run_until_collision() -> usize {
let mut ids = std::collections::HashSet::new();
let mut iters = 0;
loop {
iters += 1;
let id = TinyId::random();
if !ids.insert(id) {
break;
}
}
iters
}
11 12 13 14 15 16 17 18 19 20 21 22
fn main() {
println!("Generating {ITERS} TinyIds...");
for x in (0..(ITERS)).step_by(2) {
let id = TinyId::random();
let mut n = x + 1;
print!("#{n:03}: {id}");
print!(" | ");
let id = TinyId::random();
n += 1;
println!("#{n:03}: {id}");
}
}
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn is_valid(self) -> bool
pub fn is_valid(self) -> bool
Checks whether this TinyId
is null or has any invalid bytes.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn is_null(self) -> bool
pub fn is_null(self) -> bool
Checks whether this TinyId
is null.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn make_null(&mut self)
pub fn make_null(&mut self)
Makes this TinyId
null.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn from_str_unchecked(s: &str) -> Self
pub fn from_str_unchecked(s: &str) -> Self
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn from_u64(n: u64) -> Result<Self, TinyIdError>
pub fn from_u64(n: u64) -> Result<Self, TinyIdError>
Attempt to create a new TinyId
from a u64.
Errors
TinyIdError::InvalidLength
if the input is not 8 bytes long.TinyIdError::InvalidCharacters
if the input contains invalid chars/bytes.
sourcepub fn from_u64_unchecked(n: u64) -> Self
pub fn from_u64_unchecked(n: u64) -> Self
Creates a new TinyId
from the given u64
, without validating
that the bytes are valid.
sourcepub fn from_bytes(bytes: [u8; 8]) -> Result<Self, TinyIdError>
pub fn from_bytes(bytes: [u8; 8]) -> Result<Self, TinyIdError>
Attempt to create a new TinyId
from the given byte array.
Errors
TinyIdError::InvalidCharacters
if the input contains invalid chars/bytes.
sourcepub fn from_bytes_unchecked(bytes: [u8; 8]) -> Self
pub fn from_bytes_unchecked(bytes: [u8; 8]) -> Self
Creates a new TinyId
from the given [u8; 8]
, without validating
that the bytes are valid.
sourcepub fn starts_with(&self, input: &str) -> bool
pub fn starts_with(&self, input: &str) -> bool
Checks whether this TinyId
starts with the given string. This converts self
to string so
any associated overhead is incurred.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
sourcepub fn ends_with(&self, input: &str) -> bool
pub fn ends_with(&self, input: &str) -> bool
Checks whether this TinyId
ends with the given string. This converts self
to string so
any associated overhead is incurred.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn main() {
// Create a random ID
let rand_id = TinyId::random();
// Parse a string into a Result<TinyId, TinyIdError> for possibly unsafe / invalid ID strings
let maybe = TinyId::from_str("AAAABBBB");
assert!(maybe.is_ok());
let bad = TinyId::from_str("AAAABBB");
assert!(bad.is_err());
// Parse a string you **KNOW** is safe into a TinyId
let parsed = TinyId::from_str_unchecked("AAAABBBB");
// All expected operations are available on TinyIds
// Equality is a simple byte comparison so it should be fast and cheap!
assert_eq!(maybe.unwrap(), parsed);
// IDs may be printed using Display or Debug
println!("Random ID: {rand_id}");
println!("Parsed ID: {parsed}");
println!(" Debug ID: {parsed:?}");
// IDs are small!
println!("TinyID Size: {}", std::mem::size_of::<TinyId>());
// IDs are case-sensitive
let parsed2 = TinyId::from_str_unchecked("aaaaBBBB");
assert_ne!(parsed, parsed2);
// Check whether an ID starts with a given string. Example use case would be providing a
// list of IDs to a user, and asking for a partial string to match against so the user
// doesn't have to type the entire thing.
assert!(parsed.starts_with("AAAA"));
assert!(parsed.ends_with("BBBB"));
assert!(!parsed.starts_with("BBBB"));
// IDs are copied when assigned.
let mut switched = parsed;
assert_eq!(switched, parsed);
// Validity can be checked, and a "marker" exists for null / invalid IDs.
assert!(switched.is_valid());
assert!(!switched.is_null());
assert_ne!(switched, TinyId::null());
// Mutable IDs can be made null. This change has no effect on the `parsed` variable.
switched.make_null();
assert!(!switched.is_valid());
assert!(switched.is_null());
assert_eq!(switched, TinyId::null());
}
Trait Implementations§
source§impl Ord for TinyId
impl Ord for TinyId
source§impl PartialEq<&[u8; 8]> for TinyId
impl PartialEq<&[u8; 8]> for TinyId
source§impl PartialEq<&[u8]> for TinyId
impl PartialEq<&[u8]> for TinyId
source§impl PartialEq<&TinyId> for TinyId
impl PartialEq<&TinyId> for TinyId
source§impl PartialEq<&Vec<u8, Global>> for TinyId
impl PartialEq<&Vec<u8, Global>> for TinyId
source§impl PartialEq<[u8; 8]> for &TinyId
impl PartialEq<[u8; 8]> for &TinyId
source§impl PartialEq<[u8; 8]> for TinyId
impl PartialEq<[u8; 8]> for TinyId
source§impl PartialEq<TinyId> for &[u8; 8]
impl PartialEq<TinyId> for &[u8; 8]
source§impl PartialEq<TinyId> for &[u8]
impl PartialEq<TinyId> for &[u8]
source§impl PartialEq<TinyId> for &TinyId
impl PartialEq<TinyId> for &TinyId
source§impl PartialEq<TinyId> for &Vec<u8>
impl PartialEq<TinyId> for &Vec<u8>
source§impl PartialEq<TinyId> for [u8; 8]
impl PartialEq<TinyId> for [u8; 8]
source§impl PartialEq<TinyId> for TinyId
impl PartialEq<TinyId> for TinyId
source§impl PartialEq<TinyId> for Vec<u8>
impl PartialEq<TinyId> for Vec<u8>
source§impl PartialEq<Vec<u8, Global>> for TinyId
impl PartialEq<Vec<u8, Global>> for TinyId
source§impl PartialOrd<TinyId> for TinyId
impl PartialOrd<TinyId> for TinyId
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read more