| Crates.io | generic_constants |
| lib.rs | generic_constants |
| version | 0.1.0 |
| created_at | 2025-11-09 17:07:31.831498+00 |
| updated_at | 2025-11-09 17:07:31.831498+00 |
| description | Traits providing type-generic numeric constants (Zero, One, ..., OneHundredTwentySeven) implemented across common integer and float types. |
| homepage | https://github.com/christoffetzer/generic_constants |
| repository | https://github.com/christoffetzer/generic_constants |
| max_upload_size | |
| id | 1924295 |
| size | 119,553 |
This crate provides a family of traits, one per integer constant in the range 0 through 127. Each trait defines a single associated constant whose value is implemented across common numeric types (i8, u8, i16, u16, i32, i64, usize, f32, f64, etc.).
The traits allow writing generic code that refers to numeric constants without requiring conversion or From bounds, and without depending on unstable generic constant features.
When writing generic numeric code in Rust, one often wants to refer to numeric constants that work across different numeric types. However:
T::from(127) requires trait bounds and may not be available for all numeric types
as conversions are lossy when crossing from signed to unsigned or integer to float
Generic constant expressions are still limited in stable Rust
This crate provides a simple and predictable alternative: one trait per number, one associated constant, implemented for common numeric types.
Example
use generic_constants::OneHundredTwentySeven;
fn saturate_to_127<T: OneHundredTwentySeven + Ord>(value: T) -> T {
if value > T::ONE_HUNDRED_TWENTY_SEVEN {
T::ONE_HUNDRED_TWENTY_SEVEN
} else {
value
}
}
fn main() {
assert_eq!(saturate_to_127(200u32), 127u32);
assert_eq!(saturate_to_127(50u32), 50u32);
}
No casts, no conversion traits, no intermediate types.
Trait Structure
Each trait follows the same pattern:
pub trait OneHundredTwentySeven {
const ONE_HUNDRED_TWENTY_SEVEN: Self;
}
and is implemented for a consistent set of numeric types:
All signed and unsigned integers: i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize
Floating types: f32, f64
Example implementation:
impl OneHundredTwentySeven for i8 { const ONE_HUNDRED_TWENTY_SEVEN: Self = 127; }
impl OneHundredTwentySeven for u8 { const ONE_HUNDRED_TWENTY_SEVEN: Self = 127; }
impl OneHundredTwentySeven for f32 { const ONE_HUNDRED_TWENTY_SEVEN: Self = 127.0; }
// etc...
Traits are named using English number words: Zero, One, Two, ..., FortyTwo, ..., OneHundredTwentySeven
Associated constants follow the same English spelling, but in uppercase with underscores
This ensures:
Fully deterministic naming
No ambiguity regarding spelling, hyphens, short forms, or ordinals
Easy auto-completion in IDEs
Generic numeric algorithms
Compile-time bounds and limits
Avoiding lossy casts
Writing crates that work across integer and float types without feature gates
Type-directed constant selection
All traits are stable, pure Rust, and require no features
If desired, the range can be extended. Open an issue if you need OneHundredTwentyEight and beyond.
This project is available under:
MIT License
Apache License 2.0
At your choice.