Struct tinyid::TinyId

source ·
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§

The number of letters that make up the potential pool of characters for a TinyId.

The letter pool used during generation of a TinyId.

The byte used to represent null data / ids.

An instance of a fully null byte array, used as the basis for null ids.

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]

Create an instance of the null TinyId.

Examples found in repository?
examples/basic.rs (line 48)
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());
}

Create a new random TinyId.

Examples found in repository?
examples/collision.rs (line 30)
27
28
29
30
31
32
33
34
35
36
fn get_collision() -> usize {
    let mut ids = std::collections::HashSet::new();
    loop {
        let id = TinyId::random();
        if !ids.insert(id) {
            break;
        }
    }
    ids.len()
}
More examples
Hide additional examples
examples/collision_average.rs (line 47)
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
}
examples/sample.rs (line 14)
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}");
    }
}
examples/basic.rs (line 7)
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());
}

Checks whether this TinyId is null or has any invalid bytes.

Examples found in repository?
examples/basic.rs (line 46)
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());
}

Checks whether this TinyId is null.

Examples found in repository?
examples/basic.rs (line 47)
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());
}

Makes this TinyId null.

Examples found in repository?
examples/basic.rs (line 50)
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());
}

Convert from &str to TinyId, without checking the length or individual characters of the input.

Examples found in repository?
examples/basic.rs (line 16)
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());
}

Convert this TinyId to an array of 8 bytes.

Attempt to create a new TinyId from a u64.

Errors

Creates a new TinyId from the given u64, without validating that the bytes are valid.

Convert this TinyId to a u64 representation.

Attempt to create a new TinyId from the given byte array.

Errors

Creates a new TinyId from the given [u8; 8], without validating that the bytes are valid.

Checks whether this TinyId starts with the given string. This converts self to string so any associated overhead is incurred.

Examples found in repository?
examples/basic.rs (line 37)
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());
}

Checks whether this TinyId ends with the given string. This converts self to string so any associated overhead is incurred.

Examples found in repository?
examples/basic.rs (line 38)
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§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Formats the value using the given formatter. Read more
The associated error which can be returned from parsing.
Parses a string s to return a value of this type. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.