culit - Custom Literals in Rust
You probably know that numbers in Rust can be suffixed to specify their type, e.g. 100i32.
But did you know that syntactically any literal can have a suffix? And did you know that the suffix can be whatever you want?
This crate provides an attribute macro #[culit] for “Custom Literals”. When applied to any statement, it enables using custom literals in that statement.
= "0.6"
Note: culit does not have any dependencies such as syn or quote, and it is a simple mapping SourceCode -> SourceCode, so compile-speeds will be very fast.
Example
A NonZeroUsize literal that fails to compile if it is 0: 100nzusize
use culit;
use NonZeroUsize;
IDE Support
Hovering over the custom literals shows documentation for the macro that generates them. You can also do “goto definition”. It’s quite nice!

More Examples
Python-like f-strings: "hello {name}"f
use culit;
Duration literals: 100m, 2h…
use culit;
use Duration;
// works on functions, constants, modules, everything!
const TIME: Duration = 100d;
The possibilities are endless!
Details
#[culit] replaces every literal that has a custom suffix with a call to the macro
at crate::custom_literal::<type>::<suffix>!($value), where $value is the literal with the suffix stripped:
| literal | expansion |
|---|---|
100km |
crate::custom_literal::integer::km!(100) |
70.008e7feet |
crate::custom_literal::float::feet!(70.008e7) |
"foo"bar |
crate::custom_literal::string::bar!("foo") |
'a'ascii |
crate::custom_literal::character::ascii!('a') |
b"foo"bar |
crate::custom_literal::byte_string::bar!(b"foo") |
b'a'ascii |
crate::custom_literal::byte_character::ascii!(b'a') |
c"foo"bar |
crate::custom_literal::c_string::bar!(c"foo") |
Notes:
- Built-in suffixes like
usizeandf32do not expand, so you cannot overwrite them. - Escapes are fully processed, so there’s no
raw_byte_str.rb#"f\oo"#just becomesb"f\\oo"
Skeleton
Here’s a skeleton for the custom_literal module which must exist at crate::custom_literal.
This module adds a new literal for every type of literal:
Custom module
We look for custom literals in the crate::custom_literal module.
You can choose a custom module by passing arguments to the culit macro.
The default usage of #[culit] is identical to #[culit(crate::custom_literal)]
Global Import
This will make #[culit] globally accessible in your entire crate, without needing to import it:
extern crate culit;