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.2"
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;
use Duration;
Duration literals: 100m, 2h...
use culit;
use Duration;
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>!(...), for example:
100kmexpands tocrate::custom_literal::int::km!(100)70.8e7feetexpands tocrate::custom_literal::float::feet!(70 8 7)70is the part before the decimal8is the part after the decimal. If missing like in70e8then it defaults to07is the exponent. If missing like in70.0then it defaults to1
'a'asciiexpands tocrate::custom_literal::char::ascii!('a')b'a'asciiexpands tocrate::custom_literal::byte_char::ascii!(97)"foo"barexpands tocrate::custom_literal::str::bar!("foo")b"foo"barexpands tocrate::custom_literal::byte_str::bar!(b"foo")c"foo"barexpands tocrate::custom_literal::c_str::bar!(c"foo")
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:
Nightly
You need to use #[culit] attribute everywhere you want to use these literals. On nightly, you can apply it on the module:
While this works, I wouldn't recommend it - currently rust-analyzer is unable to properly work with custom inner attributes
that modify the whole crate. For example, if you write 0nzusize which produces a compiler error, the span of the error will point to
the macro crate::custom_literal::int::nzusize but not the actual 0nzusize, which makes it very hard to debug these