# `TypeID` Prefix
[](https://crates.io/crates/typeid_prefix)
[](https://docs.rs/typeid_prefix)
[](LICENSE)
A Rust library that implements robust validation and sanitization for the `prefix` component of [TypeIDs](https://github.com/jetpack-io/typeid), strictly adhering to the rules defined in the official **TypeID Specification**.
TypeIDs are globally unique, type-prefixed identifiers. This crate focuses *only* on the `prefix` part, ensuring it conforms to the specification's requirements for length, character set, and structure.
It can be combined with crates handling the suffix part (like the [TypeIdSuffix crate](https://crates.io/crates/typeid_suffix)) to build complete TypeID solutions, such as the [mti (Magic Type Id) crate](https://crates.io/crates/mti). For a holistic implementation of the TypeID specification, consider using the `mti` crate.
## Conformance to TypeID Specification
This crate ensures that `TypeIdPrefix` instances adhere to the following rules for prefixes as outlined in the [TypeID Specification](https://github.com/jetpack-io/typeid):
- **Maximum Length**: Prefixes must be no more than 63 characters long.
- **Character Set**: Prefixes must consist of lowercase ASCII letters (`a-z`). This crate also permits underscores (`_`) as internal separators, but ensures they do not violate start/end rules.
- **Structure**:
- Must start with a lowercase ASCII letter.
- Must end with a lowercase ASCII letter.
- Therefore, prefixes cannot start or end with an underscore.
- **Non-Empty**: An empty string is **not** a valid prefix.
The validation and sanitization logic within this crate is designed to enforce these rules rigorously.
## Features
- **Type-safe**: Ensures that `TypeID` prefixes conform to the specification.
- **Validation**: Provides robust validation for `TypeID` prefixes against specification rules.
- **Sanitization**: Offers methods to clean and sanitize input strings into valid `TypeID` prefixes.
- **Zero-cost abstractions**: Designed to have minimal runtime overhead.
- **Optional tracing**: Integrates with the `tracing` crate for logging (optional feature).
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
typeid_prefix = "1.0.0" # Replace with the latest version
```
To enable tracing support, add:
```toml
[dependencies]
typeid_prefix = { version = "1.0.0", features = ["instrument"] } # Replace with the latest version
```
## Usage
### Basic Usage
```rust
use typeid_prefix::{TypeIdPrefix, PrefixFactory}; // Assuming Sanitize is re-exported or use PrefixFactory
use std::convert::TryFrom;
// If using PrefixFactory directly:
// use typeid_prefix::PrefixFactory;
fn main() {
// Create a TypeIdPrefix from a valid string
let prefix = TypeIdPrefix::try_from("user").unwrap();
println!("Valid prefix: {}", prefix);
// Attempt to create from an invalid string (e.g., contains uppercase)
let result_invalid_char = TypeIdPrefix::try_from("Invalid_Prefix");
assert!(result_invalid_char.is_err());
if let Err(e) = result_invalid_char {
println!("Error for 'Invalid_Prefix': {}", e);
}
// Attempt to create from an empty string (invalid)
let result_empty = TypeIdPrefix::try_from("");
assert!(result_empty.is_err());
if let Err(e) = result_empty {
println!("Error for empty string: {}", e);
}
// Sanitize an invalid string
// Note: The original example used `sanitize_and_create()`.
// Assuming this comes from a trait like `Sanitize` or `PrefixFactory`.
// If `PrefixFactory` is used:
let sanitized = "Invalid_Prefix123".create_prefix_sanitized();
// let sanitized = "Invalid_Prefix123".sanitize_and_create(); // Using the provided example's trait
println!("Sanitized prefix: {}", sanitized); // Expected: "invalid_prefix"
}
```
### Validation
The `TypeIdPrefix` type ensures that all instances conform to the `TypeID` specification rules mentioned in the "Conformance" section.
```rust
use typeid_prefix::TypeIdPrefix;
use std::convert::TryFrom;
fn validate_prefix(input: &str) {
match TypeIdPrefix::try_from(input) {
Ok(prefix) => println!("'{}' is a valid prefix: {}", input, prefix),
Err(e) => println!("'{}' is an invalid prefix: {}", input, e),
}
}
fn main() {
validate_prefix("valid_prefix"); // Valid
validate_prefix("Invalid_Prefix"); // Invalid: ContainsInvalidCharacters
validate_prefix("_invalid"); // Invalid: StartsWithUnderscore or InvalidStartCharacter
validate_prefix("invalid_"); // Invalid: EndsWithUnderscore or InvalidEndCharacter
validate_prefix(""); // Invalid: IsEmpty or InvalidStartCharacter
validate_prefix("toolong_toolong_toolong_toolong_toolong_toolong_toolong_toolong"); // Invalid: ExceedsMaxLength
}
```
### Sanitization
The `PrefixFactory` trait (implemented for string types) provides `create_prefix_sanitized()` to clean and attempt to create a valid `TypeIdPrefix`.
```rust
use typeid_prefix::PrefixFactory;
fn main() {
// Using PrefixFactory
let sanitized = "Invalid String 123!@#".create_prefix_sanitized();
println!("Sanitized: {}", sanitized); // Outputs: invalidstring
let sanitized_with_underscores = "_Another Example_".create_prefix_sanitized();
println!("Sanitized: {}", sanitized_with_underscores); // Outputs: another_example
let sanitized_empty_result = "!@#$%^".create_prefix_sanitized();
println!("Sanitized (empty result): {}", sanitized_empty_result); // Outputs an empty TypeIdPrefix (default)
}
```
### Optional Tracing
When the `instrument` feature is enabled, the crate will log validation errors using the `tracing` crate:
```toml
[dependencies]
typeid_prefix = { version = "1.0.0", features = ["instrument"] } # Replace with the latest version
```
```rust
use typeid_prefix::PrefixFactory;
fn main() {
// Set up your tracing subscriber here (e.g., tracing_subscriber::fmt::init();)
// This will log if sanitization leads to an invalid state or if try_create_prefix fails.
let _attempt = "Invalid_Prefix!@#".try_create_prefix();
let _sanitized = "Invalid_Prefix!@#".create_prefix_sanitized();
// Validation errors encountered internally might be logged via tracing
}
```
## Use Cases
- **Database Systems**: Use `TypeIdPrefix` to ensure consistent and valid type prefixes for database schemas or ORM mappings, aligning with TypeID standards.
- **API Development**: Validate and sanitize user input for API endpoints that require TypeID prefixes, ensuring adherence to the specification.
- **Code Generation**: Generate valid TypeID prefixes for code generation tools or macros.
- **Configuration Management**: Ensure configuration keys or identifiers that act as TypeID prefixes conform to a consistent format.
## Safety and Correctness
This crate has been thoroughly tested and verified:
- Comprehensive unit tests
- Property-based testing with `proptest`
- Fuzz testing
- Formal verification with Kani (if applicable, confirm this is still accurate)
These measures ensure that the crate behaves correctly according to the TypeID prefix specification and aims to prevent panics under normal usage.
## Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile on Rust 1.60.0 and later.
## License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Credits
This crate implements the `prefix` validation and sanitization rules from the [TypeID Specification](https://github.com/jetpack-io/typeid) created by Jetpack.io.