Skip to content

Commit

Permalink
Merge pull request #5 from rodrimati1992/assertions
Browse files Browse the repository at this point in the history
0.2.5 release!
  • Loading branch information
rodrimati1992 authored Sep 9, 2020
2 parents 80baf3d + 6329127 commit 7a778d1
Show file tree
Hide file tree
Showing 49 changed files with 2,680 additions and 405 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ matrix:

- cargo test --features "testing"
- cargo test --features "testing fmt"
- cargo test --features "testing assert"
- cargo test --features "testing derive"
- cargo test --features "testing constant_time_as_str"
- cargo test --features "testing derive constant_time_as_str"
- cargo test --features "testing derive constant_time_as_str assert"

- MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
- echo "Installing latest nightly with Miri"
Expand All @@ -41,9 +43,11 @@ matrix:

- cargo miri test --features "testing"
- cargo miri test --features "testing fmt"
- cargo miri test --features "testing assert"
- cargo miri test --features "testing derive"
- cargo miri test --features "testing constant_time_as_str"
- cargo miri test --features "testing derive constant_time_as_str"
- cargo miri test --features "testing derive constant_time_as_str assert"


script:
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
members=[
"const_format",
"const_format_proc_macros",
"print_errors",
]
26 changes: 26 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@ This is the changelog,summarising changes in each version(some minor changes may

# 0.2

### 0.2.5

Added the "assert" cargo feature,
defining the `assertc`/`assertc_eq`/`assertc_ne` macros for
compile-time assertions with formatting.

Added custom formatting support in the `const_format::fmt`-based formatting macros,
by prefixing any argument with `|identifier|`,
accessing a `Formatter` to format that argument however one wants.

Added `concatc` macro for concatenating std/user-defined types into a `&'static str` constant.

Added `const_format::Result` alias for `std::result::Result<(), const_format::Error>`.

Added `const_format::fmt::ToResult` type for converting
`()` and `const_format::Result` to `const_format::Result`.

Added `Pwrapper::const_eq` methods for comparing many std types in
the `assertc_eq`/`assertc_ne` macros.

Added `Pwrapper::const_display_fmt` methods for `NonZero*` types.

Added support for passing `concat!(....)` as the format string.

### 0.2.0

Every single new item added requires Rust nightly to use, with at least the "fmt" cargo feature enabled.

Defined a `core::fmt`-like API with these these types:
Expand Down
150 changes: 82 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,24 @@ which have not been stabilized as of writing these docs.

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.
[`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.<br>
[`ConstDebug`] derives the [`FormatMarker`] trait,
and implements an inherent `const_debug_fmt` method for compile-time debug formatting.

The "assert" feature enables the [`assertc`], [`assertc_eq`], [`assertc_ne`] macros,
and the "fmt" feature.<br>
These macros are like the standard library assert macros, but evaluated at compile-time.

# Examples

Expand Down Expand Up @@ -116,102 +122,90 @@ assert_eq!(
```



### Formatted const panics

This example demonstrates how you can use a [`StrWriter`] to format
a compile-time panic message.
This example demonstrates how you can use the [`assertc_ne`] macro to
do compile-time inequality assertions with formatted error messages.

As of writing these docs (2020-08-29), panicking at compile-time requires a
nightly feature, and only supports passing a `&'static str` argument,
so this only works in the initialization block of `const` items.
This requires the "assert" feature,because as of writing these docs (2020-09-XX),
panicking at compile-time requires a nightly feature.

```rust
#![feature(const_mut_refs)]
#![feature(const_panic)]
#![feature(const_mut_refs)]

use const_format::{StrWriter, strwriter_as_str, writec};
use const_format::{StrWriter, assertc_ne, strwriter_as_str, writec};
use const_format::utils::str_eq;

struct PizzaError;

const fn write_message(
buffer: &mut StrWriter,
bought_by: &str,
topping: &str,
) -> Result<(), PizzaError> {
buffer.clear();
let mut writer = buffer.as_mut();
if str_eq(topping, "pineapple") {
let _ = writec!(
writer,
"\n{SEP}\n\nYou can't put pineapple on pizza, {}.\n\n{SEP}\n",
bought_by,
SEP = "----------------------------------------------------------------"
macro_rules! check_valid_pizza{
($user:expr, $topping:expr) => {
assertc_ne!(
$topping,
"pineapple",
"You can't put pineapple on pizza, {}",
$user,
);
return Err(PizzaError);
}
Ok(())
}

const CAP: usize = 256;
// Defined a `const fn` as a workaround for mutable references not
// being allowed in `const`ants.
const fn message_and_result(
bought_by: &str,
topping: &str,
) -> (StrWriter<[u8; CAP]>, Result<(), PizzaError>) {
let mut buffer = StrWriter::new([0; CAP]);
let res = write_message(&mut buffer, bought_by, topping);
(buffer, res)
}

const _: () = {
if let (buffer, Err(_)) = message_and_result("Bob", "pineapple") {
let promoted: &'static StrWriter = &{buffer};
let message = strwriter_as_str!(promoted);
panic!(message);
}
};
check_valid_pizza!("John", "salami");
check_valid_pizza!("Dave", "sausage");
check_valid_pizza!("Bob", "pineapple");

# fn main(){}
```

This is what it prints in rust nightly :
This is the compiler output,
the first compilation error is there to have an indicator of what assertion failed,
and the second is the assertion failure:

```
```text
error: any use of this value will cause an error
--> src/lib.rs:166:9
--> src/lib.rs:140:1
|
43 | / const _: () = {
44 | | if let (buffer, Err(_)) = message_and_result("Bob", "pineapple") {
45 | | let promoted: &'static StrWriter = &{buffer};
46 | | let message = strwriter_as_str!(promoted);
47 | | panic!(message);
| | ^^^^^^^^^^^^^^^^ the evaluated program panicked at '
----------------------------------------------------------------
You can't put pineapple on pizza, Bob.
----------------------------------------------------------------
', src/lib.rs:47:9
48 | | }
49 | | };
| |__-
22 | check_valid_pizza!("Bob", "pineapple");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: could not evaluate constant
--> /const_format/src/panicking.rs:32:5
|
32 | .
| ^ the evaluated program panicked at '
--------------------------------------------------------------------------------
module_path: rust_out
line: 22
assertion failed: LEFT != RIGHT
left: "pineapple"
right: "pineapple"
You can't put pineapple on pizza, Bob
--------------------------------------------------------------------------------
', /const_format/src/panicking.rs:31:1
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
```




<div id="macro-limitations"></div>

# Limitations

All of the macros from `const_format` have these limitations:

- The formatting macros that expand to
`&'static str`s can only use constants of concrete types,
so while `Type::<u8>::FOO` is fine,`Type::<T>::FOO` is not (`T` being a type parameter).
- 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](#integer-args).
Expand Down Expand Up @@ -253,14 +247,26 @@ This feature includes the `formatc`/`writec` formatting macros.
provides the `ConstDebug` derive macro to format user-defined types at compile-time.<br>
This implicitly uses the `syn` crate, so clean compiles take a bit longer than without the feature.

- "assert": implies the "fmt" feature,
enables the assertion macros.<br>
This is a separate cargo feature because:
- It uses nightly Rust features that are less stable than the "fmt" feature does.<br>
- It requires the `std` crate, because `core::panic` requires a string literal argument.


- "constant_time_as_str": implies the "fmt" feature.
An optimization that requires a few additional nightly features,
allowing 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.



# No-std support

`const_format` is unconditionally `#![no_std]`, it can be used anywhere Rust can be used.
`const_format` is `#![no_std]`, it can be used anywhere Rust can be used.

Caveat: The opt-in "assert" feature uses the `std::panic` macro to panic,
as of 2020-09-06 `core::panic` requires the argument to be a literal.

# Minimum Supported Rust Version

Expand All @@ -270,6 +276,12 @@ Features that require newer versions of Rust, or the nightly compiler,
need to be explicitly enabled with cargo features.


[`assertc`]: https://docs.rs/const_format/0.2.*/const_format/macro.assertc.html

[`assertc_eq`]: https://docs.rs/const_format/0.2.*/const_format/macro.assertc_eq.html

[`assertc_ne`]: https://docs.rs/const_format/0.2.*/const_format/macro.assertc_ne.html

[`concatcp`]: https://docs.rs/const_format/0.2.*/const_format/macro.concatcp.html

[`formatcp`]: https://docs.rs/const_format/0.2.*/const_format/macro.formatcp.html
Expand All @@ -280,6 +292,8 @@ need to be explicitly enabled with cargo features.

[`const_format::fmt`]: https://docs.rs/const_format/0.2.*/const_format/fmt/index.html

[`concatc`]: https://docs.rs/const_format/0.2.*/const_format/macro.concatc.html

[`formatc`]: https://docs.rs/const_format/0.2.*/const_format/macro.formatc.html

[`writec`]: https://docs.rs/const_format/0.2.*/const_format/macro.writec.html
Expand Down
7 changes: 4 additions & 3 deletions const_format/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "const_format"
version = "0.2.4"
version = "0.2.5"
authors = ["rodrimati1992 <[email protected]>"]
edition = "2018"
license = "Zlib"
Expand All @@ -24,16 +24,17 @@ travis-ci = { repository = "rodrimati1992/const_format_crates/" }
default = []
fmt = []
derive = ["fmt", "const_format_proc_macros/derive"]
assert = ["fmt"]
constant_time_as_str = ["fmt"]

# "private" features
debug = ["const_format_proc_macros/debug"]
testing = []
only_new_tests = ["testing"]
all = ["fmt", "derive", "constant_time_as_str"]
all = ["fmt", "derive", "constant_time_as_str", "assert"]

[dependencies.const_format_proc_macros]
version = "=0.2.0"
version = "=0.2.5"
path = "../const_format_proc_macros"

[dev-dependencies]
Expand Down
Loading

0 comments on commit 7a778d1

Please sign in to comment.