Merge pull request #342 from Kijewski/pr-no-derive

Make `derive` optional
This commit is contained in:
Guillaume Gomez 2025-02-09 21:05:55 +01:00 committed by GitHub
commit e9483747d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 212 additions and 24 deletions

View File

@ -26,7 +26,7 @@ jobs:
- run: |
set -eu
for PKG in \
examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
bench-build examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
rinja rinja_derive rinja_derive_standalone rinja_parser \
testing testing-alloc testing-no-std testing-renamed
do
@ -116,7 +116,7 @@ jobs:
cargo sort --check --check-format --grouped
set -eu
for PKG in \
examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
bench-build examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
rinja rinja_derive rinja_derive_standalone rinja_parser \
testing testing-alloc testing-no-std testing-renamed
do
@ -159,7 +159,7 @@ jobs:
strategy:
matrix:
package: [
examples/actix-web-app, examples/axum-app, examples/poem-app, examples/rocket-app, examples/salvo-app, examples/warp-app, fuzzing,
bench-build, examples/actix-web-app, examples/axum-app, examples/poem-app, examples/rocket-app, examples/salvo-app, examples/warp-app, fuzzing,
rinja, rinja_derive, rinja_derive_standalone, rinja_parser,
testing, testing-alloc, testing-no-std, testing-renamed,
]

1
bench-build/.rustfmt.toml Symbolic link
View File

@ -0,0 +1 @@
../.rustfmt.toml

18
bench-build/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "bench-build"
version = "0.3.5"
authors = ["rinja-rs developers"]
edition = "2021"
rust-version = "1.81"
publish = false
[dependencies]
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["std"] }
rinja_derive = { path = "../rinja_derive", version = "0.3.5", features = ["std"] }
[features]
default = []
derive = ["rinja/derive"]
[workspace]
members = ["."]

1
bench-build/LICENSE-APACHE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-APACHE

1
bench-build/LICENSE-MIT Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-MIT

55
bench-build/README.md Normal file
View File

@ -0,0 +1,55 @@
Run the script `./run.sh` in this directory to compare the compile compile of `rinja`
* uses feature `derive` vs
* it does not use that feature.
The output might look like:
```text
Benchmark 1: cargo run --features=derive
Time (mean ± σ): 3.378 s ± 0.041 s [User: 7.944 s, System: 1.018 s]
Range (min … max): 3.345 s … 3.424 s 3 runs
Benchmark 2: cargo run
Time (mean ± σ): 3.283 s ± 0.130 s [User: 8.400 s, System: 1.091 s]
Range (min … max): 3.141 s … 3.398 s 3 runs
Summary
cargo run ran
1.03 ± 0.04 times faster than cargo run --features=derive
----------
Benchmark 1: cargo run --release --features=derive
Time (mean ± σ): 4.733 s ± 0.050 s [User: 9.026 s, System: 0.749 s]
Range (min … max): 4.689 s … 4.788 s 3 runs
Benchmark 2: cargo run --release
Time (mean ± σ): 4.504 s ± 0.032 s [User: 9.010 s, System: 0.733 s]
Range (min … max): 4.481 s … 4.541 s 3 runs
Summary
cargo run --release ran
1.05 ± 0.01 times faster than cargo run --release --features=derive
```
This shows that while it is less convenient for small projects it might be better
to use the following setup.
This might be especially true if you are using `rinja` in a library.
Without the feature, `cargo` will be able to compile more dependencies in parallel.
```toml
# Cargo.toml
[dependencies]
rinja = { version = "0.3.5", default-features = false, features = ["std"] }
rinja_derive = { version = "0.3.5", features = ["std"] }
```
```rust
// lib.rs
use rinja::Template as _;
use rinja_derive::Template;
```
The script uses [hyperfine](https://crates.io/crates/hyperfine).
Install it with `cargo install hyperfine`.

1
bench-build/_typos.toml Symbolic link
View File

@ -0,0 +1 @@
../_typos.toml

1
bench-build/clippy.toml Symbolic link
View File

@ -0,0 +1 @@
../clippy.toml

1
bench-build/deny.toml Symbolic link
View File

@ -0,0 +1 @@
../deny.toml

20
bench-build/run.sh Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
mkdir -p target
hyperfine \
--runs=3 \
--warmup=1 \
--prepare='rm -r target' \
'cargo run --features=derive' \
'cargo run'
echo
echo ----------
echo
hyperfine \
--runs=3 \
--warmup=1 \
--prepare='rm -r target' \
'cargo run --release --features=derive' \
'cargo run --release'

47
bench-build/src/main.rs Normal file
View File

@ -0,0 +1,47 @@
use std::str::FromStr;
use rinja::Template as _;
use rinja_derive::Template;
fn main() {
let mut args = std::env::args().fuse().skip(1);
let greeting = args.next();
let user = args.next();
let tmpl = HelloWorld {
greeting: greeting.as_deref().unwrap_or("hi").parse().unwrap(),
user: user.as_deref().unwrap_or("user"),
};
println!("{}", tmpl.render().unwrap());
}
#[derive(Debug, Clone, Copy, Template)]
#[template(path = "hello_world.html")]
struct HelloWorld<'a> {
greeting: Greeting,
user: &'a str,
}
#[derive(Debug, Clone, Copy, Template)]
#[template(path = "greeting.html")]
enum Greeting {
#[template(block = "hello")]
Hello,
#[template(block = "hey")]
Hey,
#[template(block = "hi")]
Hi,
}
impl FromStr for Greeting {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"hello" => Ok(Self::Hello),
"hey" => Ok(Self::Hey),
"hi" => Ok(Self::Hi),
_ => Err("Valid greetings: <hello | hey | hi>"),
}
}
}

View File

@ -0,0 +1,11 @@
{%- block hello -%}
Hello
{%- endblock -%}
{%- block hey -%}
Hey
{%- endblock -%}
{%- block hi -%}
Hi
{%- endblock -%}

View File

@ -0,0 +1 @@
<h1>{{greeting}}, {{user}}!</h1>

1
bench-build/tomlfmt.toml Symbolic link
View File

@ -0,0 +1 @@
../tomlfmt.toml

View File

@ -35,7 +35,7 @@ Without `default-features = false`, i.e with default features enabled,
the following features are automatically selected for you:
```toml
default = ["config", "std", "urlencode"]
default = ["config", "derive", "std", "urlencode"]
```
This should encompass most features an average user of rinja might need.
@ -44,6 +44,24 @@ This should encompass most features an average user of rinja might need.
and if you want it to be usable in by other users and in **other projects**,
then you should probably **opt-out of features you do not need**.*
### `"derive"`
<blockquote class="right" style="padding:0.5ex 1ex; margin:0 0 1ex 1ex; font-size:80%">
enabled by <code>"default"</code>
</blockquote>
This feature enables `#[derive(Template)]`. Without it the trait `rinja::Template` will still be
available, but if you want to derive a template, you have to manually depend on `rinja_derive`.
`rinja_derive` should be used with the same features as `rinja`.
Not using this feature might be useful e.g. if you are writing a library with manual filters
for rinja, without any templates. It might also very slightly speed-up the compilation,
because more dependencies can be compiled in parallel, because `rinja` won't transitively depend
on e.g. `syn` or `proc-macro2`. On the author's PC the compilation of a trivial hello-world example
was about 0.2s faster without the feature when compiled in release mode.
*If you are writing a library that uses rinja, consider **not using** this default-feature.*
### `"config"`
<blockquote class="right" style="padding:0.5ex 1ex; margin:0 0 1ex 1ex; font-size:80%">

View File

@ -24,10 +24,11 @@ name = "escape"
harness = false
[dependencies]
rinja_derive = { version = "=0.3.5", path = "../rinja_derive" }
itoa = "1.0.11"
# needed by feature "derive"
rinja_derive = { version = "=0.3.5", path = "../rinja_derive", default-features = false, optional = true }
# needed by feature "serde_json"
serde = { version = "1.0", optional = true, default-features = false }
serde_json = { version = "1.0", optional = true, default-features = false }
@ -43,24 +44,25 @@ criterion = "0.5"
maintenance = { status = "actively-developed" }
[features]
default = ["config", "std", "urlencode"]
full = ["default", "blocks", "code-in-doc", "serde_json"]
default = ["config", "derive", "std", "urlencode", "rinja_derive?/default"]
full = ["default", "blocks", "code-in-doc", "serde_json", "rinja_derive?/full"]
alloc = [
"rinja_derive/alloc",
"rinja_derive?/alloc",
"serde?/alloc",
"serde_json?/alloc",
"percent-encoding?/alloc"
"percent-encoding?/alloc",
]
blocks = ["rinja_derive/blocks"]
code-in-doc = ["rinja_derive/code-in-doc"]
config = ["rinja_derive/config"]
serde_json = ["rinja_derive/serde_json", "dep:serde", "dep:serde_json"]
blocks = ["rinja_derive?/blocks"]
code-in-doc = ["rinja_derive?/code-in-doc"]
config = ["rinja_derive?/config"]
derive = ["rinja_derive"]
serde_json = ["rinja_derive?/serde_json", "dep:serde", "dep:serde_json"]
std = [
"alloc",
"rinja_derive/std",
"rinja_derive?/std",
"serde?/std",
"serde_json?/std",
"percent-encoding?/std"
"percent-encoding?/std",
]
urlencode = ["rinja_derive/urlencode", "dep:percent-encoding"]
urlencode = ["rinja_derive?/urlencode", "dep:percent-encoding"]

View File

@ -34,8 +34,8 @@
//! }
//!
//! assert_eq!(
//! Footer { year: 2024, enterprise: "<em>Rinja</em> developers" }.to_string(),
//! "<p>© 2024 &#60;EM&#62;RINJA&#60;/EM&#62; DEVELOPERS</p>",
//! Footer { year: 2025, enterprise: "<em>Rinja</em> developers" }.to_string(),
//! "<p>© 2025 &#60;EM&#62;RINJA&#60;/EM&#62; DEVELOPERS</p>",
//! );
//! // In here you see can Rinja's auto-escaping. You, the developer,
//! // can easily disable the auto-escaping with the `|safe` filter,
@ -78,6 +78,7 @@ use core::fmt;
#[cfg(feature = "std")]
use std::io;
#[cfg(feature = "derive")]
pub use rinja_derive::Template;
#[doc(hidden)]

View File

@ -38,14 +38,19 @@ prettyplease = "0.2.20"
similar = "2.6.0"
syn = { version = "2.0.3", features = ["full"] }
# must be the same feature list as for rinja
[features]
default = ["config", "derive", "std", "urlencode"]
full = ["default", "blocks", "code-in-doc", "serde_json"]
alloc = []
blocks = ["syn/full"]
code-in-doc = ["dep:pulldown-cmark"]
config = ["dep:basic-toml", "dep:serde", "dep:serde_derive", "parser/config"]
urlencode = []
derive = []
serde_json = []
std = ["alloc"]
urlencode = []
[lints.rust]
# Used in `rinja_derive_standalone` which uses the same source folder, but is not a proc-macro.

View File

@ -47,11 +47,14 @@ syn = { version = "2.0.3", features = ["full"] }
default = ["__standalone"]
__standalone = []
alloc = []
blocks = ["syn/full"]
code-in-doc = ["dep:pulldown-cmark"]
config = ["dep:basic-toml", "dep:serde", "dep:serde_derive", "parser/config"]
urlencode = []
derive = []
serde_json = []
std = ["alloc"]
urlencode = []
[lints.rust]
# Used in `rinja_derive` which uses the same source folder, but is a proc-macro.

View File

@ -7,6 +7,6 @@ rust-version = "1.81"
publish = false
[dev-dependencies]
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["alloc"] }
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["alloc", "derive"] }
assert_matches = "1.5.0"

View File

@ -7,6 +7,6 @@ rust-version = "1.81"
publish = false
[dev-dependencies]
rinja = { path = "../rinja", version = "0.3.5", default-features = false }
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["derive"] }
assert_matches = "1.5.0"

View File

@ -7,6 +7,6 @@ rust-version = "1.81"
publish = false
[dev-dependencies]
some_name = { package = "rinja", path = "../rinja", version = "0.3.5", default-features = false }
some_name = { package = "rinja", path = "../rinja", version = "0.3.5", default-features = false, features = ["derive"] }
assert_matches = "1.5.0"