Crates.io | const_format |
lib.rs | const_format |
version | |
source | src |
created_at | 2020-08-17 03:38:43.263493 |
updated_at | 2024-12-06 21:10:12.913219 |
description | Compile-time string formatting |
homepage | |
repository | https://github.com/rodrimati1992/const_format_crates/ |
max_upload_size | |
id | 277417 |
Cargo.toml error: | TOML parse error at line 25, column 1 | 25 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
Compile-time string formatting.
This crate provides types and macros for formatting strings at compile-time.
There are some features that require a variety of Rust versions, the sections below describe the features that are available for each version.
These macros are available in Rust 1.57.0:
concatcp
:
Concatenates integers
, bool
, char
, and &str
constants into a &'static str
constant.
formatcp
:
format
-like formatting which takes integers
, bool
, char
, and &str
constants,
and emits a &'static str
constant.
str_get
:
Indexes a &'static str
constant, returning None
when the index is out of bounds.
str_index
:
Indexes a &'static str
constant.
str_repeat
:
Creates a &'static str
by repeating a &'static str
constant times
times.
str_splice
:
Replaces a substring in a &'static str
constant.
map_ascii_case
:
Converts a &'static str
constant to a different casing style,
determined by a Case
argument.
str_replace
:
Replaces all the instances of a pattern in a &'static str
constant with
another &'static str
constant.
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
).
The "rust_1_64"
feature enables these macros:
str_split
: splits a string constantBy 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 str
constant.
formatc
:
format
-like macro that can format many standard library and user defined types into
a &'static str
constant.
writec
:
write
-like macro that can format many standard library and user defined types
into a type that implements WriteMarker
.
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.
use const_format::concatcp;
const NAME: &str = "Bob";
const FOO: &str = concatcp!(NAME, ", age ", 21u8,"!");
assert_eq!(FOO, "Bob, age 21!");
use const_format::formatcp;
const NAME: &str = "John";
const FOO: &str = formatcp!("{NAME}, age {}!", compute_age(NAME));
assert_eq!(FOO, "John, age 24!");
const fn compute_age(s: &str) -> usize { s.len() * 6 }
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_format::{ConstDebug, formatc};
#[derive(ConstDebug)]
struct Message{
ip: [Octet; 4],
value: &'static str,
}
#[derive(ConstDebug)]
struct Octet(u8);
const MSG: Message = Message{
ip: [Octet(127), Octet(0), Octet(0), Octet(1)],
value: "Hello, World!",
};
const FOO: &str = formatc!("{:?}", MSG);
assert_eq!(
FOO,
"Message { ip: [Octet(127), Octet(0), Octet(0), Octet(1)], value: \"Hello, World!\" }"
);
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 const_format::assertcp_ne;
macro_rules! check_valid_pizza{
($user:expr, $topping:expr) => {
assertcp_ne!(
$topping,
"pineapple",
"You can't put pineapple on pizza, {}",
$user,
);
}
}
check_valid_pizza!("John", "salami");
check_valid_pizza!("Dave", "sausage");
check_valid_pizza!("Bob", "pineapple");
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
All of the macros from const_format
have these limitations:
The formatting macros that expand to
&'static str
s can only use constants from concrete types,
so while a Type::<u8>::FOO
argument would be fine,
Type::<T>::FOO
would not be (T
being 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 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!(const_format::concatcp!(N + 1, 2 + N), "23");
assert_eq!(const_format::concatcp!(2u32, 2 + 1u8, 3u8 + 1), "234");
Example of what does not compile:
assert_eq!(const_format::concatcp!(1 + 1, 2 + 1), "23");
None right now.
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:
[dependencies]
cfmt = {version = "0.*", package = "const_format"}
"fmt"
: Enables the std::fmt
-like API and "rust_1_83"
feature,
requires Rust 1.83.0 because it uses mutable references in const fn.
This feature includes the formatc
/writec
formatting macros.
"derive"
: requires Rust 1.83.0, implies the "fmt"
feature,
provides the ConstDebug
derive macro to format user-defined types at compile-time.
This implicitly uses the syn
crate, so clean compiles take a bit longer than without the feature.
"assertc"
: requires Rust 1.83.0, implies the "fmt"
feature,
enables the assertc
, assertc_eq
, and assertc_ne
assertion macros.
This feature was previously named "assert"
,
but it was renamed to avoid confusion with the "assertcp"
feature.
"assertcp"
:
Enables the assertcp
, assertcp_eq
, and assertcp_ne
assertion macros.
"rust_1_64"
: Enables the str_split
macro.
Allows the as_bytes_alt
methods and slice_up_to_len_alt
methods 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.
const_format
is unconditionally #![no_std]
, it can be used anywhere Rust can be used.
const_format
requires Rust 1.57.0.
Features that require newer versions of Rust, or the nightly compiler, need to be explicitly enabled with cargo features.