Skip to content

Commit 7b75e7c

Browse files
committed
Make derive optional
This is the same as in e.g. `serde` with the feature of the same name. If you manually depend on `rinja_derive`, then you can make better use of your multi-core setup.
1 parent a0e19aa commit 7b75e7c

File tree

22 files changed

+213
-25
lines changed

22 files changed

+213
-25
lines changed

.github/workflows/rust.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- run: |
2727
set -eu
2828
for PKG in \
29-
examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
29+
bench-build examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
3030
rinja rinja_derive rinja_derive_standalone rinja_parser \
3131
testing testing-alloc testing-no-std testing-renamed
3232
do
@@ -116,7 +116,7 @@ jobs:
116116
cargo sort --check --check-format --grouped
117117
set -eu
118118
for PKG in \
119-
examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
119+
bench-build examples/actix-web-app examples/axum-app examples/poem-app examples/rocket-app examples/salvo-app examples/warp-app fuzzing \
120120
rinja rinja_derive rinja_derive_standalone rinja_parser \
121121
testing testing-alloc testing-no-std testing-renamed
122122
do
@@ -159,7 +159,7 @@ jobs:
159159
strategy:
160160
matrix:
161161
package: [
162-
examples/actix-web-app, examples/axum-app, examples/poem-app, examples/rocket-app, examples/salvo-app, examples/warp-app, fuzzing,
162+
bench-build, examples/actix-web-app, examples/axum-app, examples/poem-app, examples/rocket-app, examples/salvo-app, examples/warp-app, fuzzing,
163163
rinja, rinja_derive, rinja_derive_standalone, rinja_parser,
164164
testing, testing-alloc, testing-no-std, testing-renamed,
165165
]

bench-build/.rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../.rustfmt.toml

bench-build/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "bench-build"
3+
version = "0.3.5"
4+
authors = ["rinja-rs developers"]
5+
edition = "2021"
6+
rust-version = "1.81"
7+
publish = false
8+
9+
[dependencies]
10+
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["std"] }
11+
rinja_derive = { path = "../rinja_derive", version = "0.3.5", features = ["std"] }
12+
13+
[features]
14+
default = []
15+
derive = ["rinja/derive"]
16+
17+
[workspace]
18+
members = ["."]

bench-build/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-APACHE

bench-build/LICENSE-MIT

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-MIT

bench-build/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
Run the script `./run.sh` in this directory to compare the compile compile if `rinja`
2+
3+
* uses feature `derive` vs
4+
* it does not use that feature.
5+
6+
The output might look like:
7+
8+
```text
9+
Benchmark 1: cargo run --features=derive
10+
Time (mean ± σ): 3.378 s ± 0.041 s [User: 7.944 s, System: 1.018 s]
11+
Range (min … max): 3.345 s … 3.424 s 3 runs
12+
13+
Benchmark 2: cargo run
14+
Time (mean ± σ): 3.283 s ± 0.130 s [User: 8.400 s, System: 1.091 s]
15+
Range (min … max): 3.141 s … 3.398 s 3 runs
16+
17+
Summary
18+
cargo run ran
19+
1.03 ± 0.04 times faster than cargo run --features=derive
20+
21+
----------
22+
23+
Benchmark 1: cargo run --release --features=derive
24+
Time (mean ± σ): 4.733 s ± 0.050 s [User: 9.026 s, System: 0.749 s]
25+
Range (min … max): 4.689 s … 4.788 s 3 runs
26+
27+
Benchmark 2: cargo run --release
28+
Time (mean ± σ): 4.504 s ± 0.032 s [User: 9.010 s, System: 0.733 s]
29+
Range (min … max): 4.481 s … 4.541 s 3 runs
30+
31+
Summary
32+
cargo run --release ran
33+
1.05 ± 0.01 times faster than cargo run --release --features=derive
34+
```
35+
36+
This shows that – while it is less convenient – for small projects it might be better
37+
to use the following setup.
38+
This might be especially true if you are using `rinja` in a library.
39+
Without the feature, `cargo` will be able to compile more dependencies in parallel.
40+
41+
```toml
42+
# Cargo.toml
43+
[dependencies]
44+
rinja = { version = "0.3.5", default-features = false, features = ["std"] }
45+
rinja_derive = { version = "0.3.5", features = ["std"] }
46+
```
47+
48+
```rust
49+
// lib.rs
50+
use rinja::Template as _;
51+
use rinja_derive::Template;
52+
```
53+
54+
The script uses [hyperfine](https://crates.io/crates/hyperfine).
55+
Install it with `cargo install hyperfine`.

bench-build/_typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../_typos.toml

bench-build/clippy.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../clippy.toml

bench-build/deny.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../deny.toml

bench-build/run.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
cd "$(dirname "${BASH_SOURCE[0]}")"
4+
5+
mkdir -p target
6+
hyperfine \
7+
--runs=3 \
8+
--warmup=1 \
9+
--prepare='rm -r target' \
10+
'cargo run --features=derive' \
11+
'cargo run'
12+
echo
13+
echo ----------
14+
echo
15+
hyperfine \
16+
--runs=3 \
17+
--warmup=1 \
18+
--prepare='rm -r target' \
19+
'cargo run --release --features=derive' \
20+
'cargo run --release'

bench-build/src/main.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::str::FromStr;
2+
3+
use rinja::Template as _;
4+
use rinja_derive::Template;
5+
6+
fn main() {
7+
let mut args = std::env::args().fuse().skip(1);
8+
let greeting = args.next();
9+
let user = args.next();
10+
11+
let tmpl = HelloWorld {
12+
greeting: greeting.as_deref().unwrap_or("hi").parse().unwrap(),
13+
user: user.as_deref().unwrap_or("user"),
14+
};
15+
println!("{}", tmpl.render().unwrap());
16+
}
17+
18+
#[derive(Debug, Clone, Copy, Template)]
19+
#[template(path = "hello_world.html")]
20+
struct HelloWorld<'a> {
21+
greeting: Greeting,
22+
user: &'a str,
23+
}
24+
25+
#[derive(Debug, Clone, Copy, Template)]
26+
#[template(path = "greeting.html")]
27+
enum Greeting {
28+
#[template(block = "hello")]
29+
Hello,
30+
#[template(block = "hey")]
31+
Hey,
32+
#[template(block = "hi")]
33+
Hi,
34+
}
35+
36+
impl FromStr for Greeting {
37+
type Err = &'static str;
38+
39+
fn from_str(s: &str) -> Result<Self, Self::Err> {
40+
match s {
41+
"hello" => Ok(Self::Hello),
42+
"hey" => Ok(Self::Hey),
43+
"hi" => Ok(Self::Hi),
44+
_ => Err("Valid greetings: <hello | hey | hi>"),
45+
}
46+
}
47+
}

bench-build/templates/greeting.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{%- block hello -%}
2+
Hello
3+
{%- endblock -%}
4+
5+
{%- block hey -%}
6+
Hey
7+
{%- endblock -%}
8+
9+
{%- block hi -%}
10+
Hi
11+
{%- endblock -%}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>{{greeting}}, {{user}}!</h1>

bench-build/tomlfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../tomlfmt.toml

book/src/features.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Without `default-features = false`, i.e with default features enabled,
3535
the following features are automatically selected for you:
3636

3737
```toml
38-
default = ["config", "std", "urlencode"]
38+
default = ["config", "derive", "std", "urlencode"]
3939
```
4040

4141
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.
4444
and if you want it to be usable in by other users and in **other projects**,
4545
then you should probably **opt-out of features you do not need**.*
4646

47+
### `"derive"`
48+
49+
<blockquote class="right" style="padding:0.5ex 1ex; margin:0 0 1ex 1ex; font-size:80%">
50+
enabled by <code>"default"</code>
51+
</blockquote>
52+
53+
This feature enables `#[derive(Template)]`. Without it the trait `rinja::Template` will still be
54+
available, but if you want to derive a template, you have to manually depend on `rinja_derive`.
55+
`rinja_derive` should be used with the same features as `rinja`.
56+
57+
Not using this feature might be useful e.g. if you are writing a library with manual filters
58+
for rinja, without any templates. It might also very slightly speed-up the compilation,
59+
because more dependencies can be compiled in parallel, because `rinja` won't transitively depend
60+
on e.g. `syn` or `proc-macro2`. On the author's PC the compilation of a trivial hello-world example
61+
was about 0.2s faster without the feature when compiled in release mode.
62+
63+
*If you are writing a library that uses rinja, consider **not using** this default-feature.*
64+
4765
### `"config"`
4866

4967
<blockquote class="right" style="padding:0.5ex 1ex; margin:0 0 1ex 1ex; font-size:80%">

rinja/Cargo.toml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ name = "escape"
2424
harness = false
2525

2626
[dependencies]
27-
rinja_derive = { version = "=0.3.5", path = "../rinja_derive" }
28-
2927
itoa = "1.0.11"
3028

29+
# needed by feature "derive"
30+
rinja_derive = { version = "=0.3.5", path = "../rinja_derive", default-features = false, optional = true }
31+
3132
# needed by feature "serde_json"
3233
serde = { version = "1.0", optional = true, default-features = false }
33-
serde_json = { version = "1.0", optional = true, default-features = false, features = [] }
34+
serde_json = { version = "1.0", optional = true, default-features = false }
3435

3536
# needed by feature "urlencode"
3637
percent-encoding = { version = "2.1.0", optional = true, default-features = false }
@@ -43,24 +44,25 @@ criterion = "0.5"
4344
maintenance = { status = "actively-developed" }
4445

4546
[features]
46-
default = ["config", "std", "urlencode"]
47-
full = ["default", "blocks", "code-in-doc", "serde_json"]
47+
default = ["config", "derive", "std", "urlencode", "rinja_derive?/default"]
48+
full = ["default", "blocks", "code-in-doc", "serde_json", "rinja_derive?/full"]
4849

4950
alloc = [
50-
"rinja_derive/alloc",
51+
"rinja_derive?/alloc",
5152
"serde?/alloc",
5253
"serde_json?/alloc",
53-
"percent-encoding?/alloc"
54+
"percent-encoding?/alloc",
5455
]
55-
blocks = ["rinja_derive/blocks"]
56-
code-in-doc = ["rinja_derive/code-in-doc"]
57-
config = ["rinja_derive/config"]
58-
serde_json = ["rinja_derive/serde_json", "dep:serde", "dep:serde_json"]
56+
blocks = ["rinja_derive?/blocks"]
57+
code-in-doc = ["rinja_derive?/code-in-doc"]
58+
config = ["rinja_derive?/config"]
59+
derive = ["rinja_derive"]
60+
serde_json = ["rinja_derive?/serde_json", "dep:serde", "dep:serde_json"]
5961
std = [
6062
"alloc",
61-
"rinja_derive/std",
63+
"rinja_derive?/std",
6264
"serde?/std",
6365
"serde_json?/std",
64-
"percent-encoding?/std"
66+
"percent-encoding?/std",
6567
]
66-
urlencode = ["rinja_derive/urlencode", "dep:percent-encoding"]
68+
urlencode = ["rinja_derive?/urlencode", "dep:percent-encoding"]

rinja/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
//! }
3535
//!
3636
//! assert_eq!(
37-
//! Footer { year: 2024, enterprise: "<em>Rinja</em> developers" }.to_string(),
38-
//! "<p>© 2024 &#60;EM&#62;RINJA&#60;/EM&#62; DEVELOPERS</p>",
37+
//! Footer { year: 2025, enterprise: "<em>Rinja</em> developers" }.to_string(),
38+
//! "<p>© 2025 &#60;EM&#62;RINJA&#60;/EM&#62; DEVELOPERS</p>",
3939
//! );
4040
//! // In here you see can Rinja's auto-escaping. You, the developer,
4141
//! // can easily disable the auto-escaping with the `|safe` filter,
@@ -78,6 +78,7 @@ use core::fmt;
7878
#[cfg(feature = "std")]
7979
use std::io;
8080

81+
#[cfg(feature = "derive")]
8182
pub use rinja_derive::Template;
8283

8384
#[doc(hidden)]

rinja_derive/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ prettyplease = "0.2.20"
3737
similar = "2.6.0"
3838
syn = { version = "2.0.3", features = ["full"] }
3939

40+
# must be the same feature list as for rinja
4041
[features]
42+
default = ["config", "derive", "std", "urlencode"]
43+
full = ["default", "blocks", "code-in-doc", "serde_json"]
44+
4145
alloc = []
4246
blocks = ["syn/full"]
4347
code-in-doc = ["dep:pulldown-cmark"]
4448
config = ["dep:serde", "dep:basic-toml", "parser/config"]
45-
urlencode = []
49+
derive = []
4650
serde_json = []
4751
std = ["alloc"]
52+
urlencode = []
4853

4954
[lints.rust]
5055
# Used in `rinja_derive_standalone` which uses the same source folder, but is not a proc-macro.

rinja_derive_standalone/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@ syn = { version = "2.0.3", features = ["full"] }
4646
default = ["__standalone"]
4747
__standalone = []
4848

49+
alloc = []
4950
blocks = ["syn/full"]
5051
code-in-doc = ["dep:pulldown-cmark"]
5152
config = ["dep:serde", "dep:basic-toml", "parser/config"]
52-
urlencode = []
53+
derive = []
5354
serde_json = []
55+
std = ["alloc"]
56+
urlencode = []
5457

5558
[lints.rust]
5659
# Used in `rinja_derive` which uses the same source folder, but is a proc-macro.

testing-alloc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ rust-version = "1.81"
77
publish = false
88

99
[dev-dependencies]
10-
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["alloc"] }
10+
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["alloc", "derive"] }
1111

1212
assert_matches = "1.5.0"

testing-no-std/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ rust-version = "1.81"
77
publish = false
88

99
[dev-dependencies]
10-
rinja = { path = "../rinja", version = "0.3.5", default-features = false }
10+
rinja = { path = "../rinja", version = "0.3.5", default-features = false, features = ["derive"] }
1111

1212
assert_matches = "1.5.0"

testing-renamed/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ rust-version = "1.81"
77
publish = false
88

99
[dev-dependencies]
10-
some_name = { package = "rinja", path = "../rinja", version = "0.3.5", default-features = false }
10+
some_name = { package = "rinja", path = "../rinja", version = "0.3.5", default-features = false, features = ["derive"] }
1111

1212
assert_matches = "1.5.0"

0 commit comments

Comments
 (0)