Compile-time string formatting.
This crate provides types and macros for formatting strings at compile-time.
Rust versions
There are some features that require a variety of Rust versions, the sections below describe the features that are available for each version.
Rust 1.60.0
These macros are available in Rust 1.60.0:
-
concatcp: Concatenatesintegers,bool,char, and&strconstants into a&'static strconstant. -
formatcp:format-like formatting which takesintegers,bool,char, and&strconstants, and emits a&'static strconstant. -
str_get: Indexes a&'static strconstant, returningNonewhen the index is out of bounds. -
str_index: Indexes a&'static strconstant. -
str_repeat: Creates a&'static strby repeating a&'static strconstanttimestimes. -
str_splice: Replaces a substring in a&'static strconstant. -
map_ascii_case: Converts a&'static strconstant to a different casing style, determined by aCaseargument. -
str_replace: Replaces all the instances of a pattern in a&'static strconstant with another&'static strconstant.
The "assertcp" feature enables the assertcp, assertcp_eq,
and assertcp_ne macros.
These macros are like the standard library assert macros,
but evaluated at compile-time,
with the limitation that they can only have primitive types as arguments
(just like concatcp and formatcp).
Rust 1.64.0
The "rust_1_64" feature enables these macros:
str_split: splits a string constant
Rust 1.83.0
By enabling the "fmt" feature, you can use a std::fmt-like API.
This requires Rust 1.83.0, because it uses mutable references in const fn.
All the other features of this crate are implemented on top of the const_format::fmt API:
-
concatc: Concatenates many standard library and user defined types into a&'static strconstant. -
formatc:format-like macro that can format many standard library and user defined types into a&'static strconstant. -
writec:write-like macro that can format many standard library and user defined types into a type that implementsWriteMarker.
The "derive" feature enables the ConstDebug macro,
and the "fmt" feature.
ConstDebug derives the FormatMarker trait,
and implements an inherent const_debug_fmt method for compile-time debug formatting.
The "assertc" feature enables the assertc, assertc_eq, assertc_ne macros,
and the "fmt" feature.
These macros are like the standard library assert macros, but evaluated at compile-time.
Examples
Concatenation of primitive types
use concatcp;
const NAME: &str = "Bob";
const FOO: &str = concatcp!;
assert_eq!;
Formatting primitive types
use formatcp;
const NAME: &str = "John";
const FOO: &str = formatcp!;
assert_eq!;
const
Formatting custom types
This example demonstrates how you can use the ConstDebug derive macro,
and then format the type into a &'static str constant.
This example requires Rust 1.83.0, and the "derive" feature.
use ;
;
const MSG: Message = Message;
const FOO: &str = formatc!;
assert_eq!;
Formatted const assertions
This example demonstrates how you can use the assertcp_ne macro to
do compile-time inequality assertions with formatted error messages.
This requires the "assertcp" feature.
use assertcp_ne;
check_valid_pizza!;
check_valid_pizza!;
check_valid_pizza!;
This is the compiler output:
error[E0080]: evaluation of constant value failed
--> src/lib.rs:178:27
|
20 | check_valid_pizza!("Bob", "pineapple");
| ^^^^^^^^^^^ the evaluated program panicked at '
assertion failed: `(left != right)`
left: `"pineapple"`
right: `"pineapple"`
You can't put pineapple on pizza, Bob
', src/lib.rs:20:27
Limitations
All of the macros from const_format have these limitations:
-
The formatting macros that expand to
&'static strs can only use constants from concrete types, so while aType::<u8>::FOOargument would be fine,Type::<T>::FOOwould not be (Tbeing a type parameter). -
Integer arguments must have a type inferrable from context, more details in the Integer arguments section.
-
They cannot be used places that take string literals. So
#[doc = "foobar"]cannot be replaced with#[doc = concatcp!("foo", "bar") ].
Integer arguments
Integer arguments must have a type inferrable from context. so if you only pass an integer literal it must have a suffix.
Example of what does compile:
const N: u32 = 1;
assert_eq!;
assert_eq!;
Example of what does not compile:
assert_eq!;
Plans
None right now.
Renaming crate
All function-like macros from const_format can be used when the crate is renamed.
The ConstDebug derive macro has the #[cdeb(crate = "foo::bar")] attribute to
tell it where to find the const_format crate.
Example of renaming the const_format crate in the Cargo.toml file:
[]
= { = "0.*", = "const_format"}
Cargo features
-
"fmt": Enables thestd::fmt-like API and"rust_1_83"feature, requires Rust 1.83.0 because it uses mutable references in const fn. This feature includes theformatc/writecformatting macros. -
"derive": requires Rust 1.83.0, implies the"fmt"feature, provides theConstDebugderive macro to format user-defined types at compile-time. This implicitly uses thesyncrate, so clean compiles take a bit longer than without the feature. -
"assertc": requires Rust 1.83.0, implies the"fmt"feature, enables theassertc,assertc_eq, andassertc_neassertion macros. This feature was previously named"assert", but it was renamed to avoid confusion with the"assertcp"feature. -
"assertcp": Enables theassertcp,assertcp_eq, andassertcp_neassertion macros. -
"rust_1_64": Enables thestr_splitmacro. Allows theas_bytes_altmethods andslice_up_to_len_altmethods to run in constant time, rather than linear time (proportional to the truncated part of the slice). -
"rust_1_83": Enables the"rust_1_64"feature and makes macros that evaluate to a value compatible with inline const patterns.
No-std support
const_format is unconditionally #![no_std], it can be used anywhere Rust can be used.
Minimum Supported Rust Version
const_format requires Rust 1.60.0.
Features that require newer versions of Rust, or the nightly compiler, need to be explicitly enabled with cargo features.