Skip to content

Commit a749914

Browse files
authored
Merge pull request #147 from kaj/iter-strings
Get rid of itertools dependency.
2 parents 911c601 + 75ff8c7 commit a749914

File tree

6 files changed

+151
-128
lines changed

6 files changed

+151
-128
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ project adheres to
1111
## Unreleased
1212

1313
* Updated `nom` to 8.0.0, and added `nom-language`.
14+
* Removed `itertools` depenendency (PR #147).
1415
* MSRV is now 1.65.0, as required by `nom` 8.0.
1516

1617

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ tide013 = ["http-types"]
2525
[dependencies]
2626
base64 = "0.22.1"
2727
bytecount = "0.6.0"
28-
itertools = "0.14.0"
2928
md5 = "0.7"
3029
nom = "8.0.0"
3130
nom-language = "0.1.0"

src/lib.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ mod templateexpression;
154154
use parseresult::show_errors;
155155
use std::env;
156156
use std::error::Error;
157-
use std::fmt::{self, Debug, Display};
157+
use std::fmt::{self, Debug, Display, Write as _};
158158
use std::fs::{create_dir_all, read_dir, File};
159-
use std::io::{self, Read, Write};
159+
use std::io::{self, Read};
160160
use std::path::{Path, PathBuf};
161161
use template::template;
162162

@@ -211,7 +211,7 @@ pub use staticfiles::StaticFiles;
211211
///
212212
/// [cargo]: https://doc.rust-lang.org/cargo/
213213
pub struct Ructe {
214-
f: Vec<u8>,
214+
f: String,
215215
outdir: PathBuf,
216216
}
217217

@@ -241,32 +241,32 @@ impl Ructe {
241241
///
242242
/// [cargo]: https://doc.rust-lang.org/cargo/
243243
pub fn new(outdir: PathBuf) -> Result<Ructe> {
244-
let mut f = Vec::with_capacity(512);
244+
let mut f = String::with_capacity(512);
245245
let outdir = outdir.join("templates");
246246
create_dir_all(&outdir)?;
247-
f.write_all(b"pub mod templates {\n")?;
247+
f.write_str("pub mod templates {\n")?;
248248
write_if_changed(
249249
&outdir.join("_utils.rs"),
250-
include_bytes!(concat!(
250+
include_str!(concat!(
251251
env!("CARGO_MANIFEST_DIR"),
252252
"/src/templates/utils.rs"
253253
)),
254254
)?;
255-
f.write_all(
256-
b"#[doc(hidden)]\nmod _utils;\n\
257-
#[doc(inline)]\npub use self::_utils::*;\n\n",
255+
f.write_str(
256+
"#[doc(hidden)]\nmod _utils;\n\
257+
#[doc(inline)]\npub use self::_utils::*;\n\n",
258258
)?;
259259
if cfg!(feature = "warp03") {
260260
write_if_changed(
261261
&outdir.join("_utils_warp03.rs"),
262-
include_bytes!(concat!(
262+
include_str!(concat!(
263263
env!("CARGO_MANIFEST_DIR"),
264264
"/src/templates/utils_warp03.rs"
265265
)),
266266
)?;
267-
f.write_all(
268-
b"#[doc(hidden)]\nmod _utils_warp03;\n\
269-
#[doc(inline)]\npub use self::_utils_warp03::*;\n\n",
267+
f.write_str(
268+
"#[doc(hidden)]\nmod _utils_warp03;\n\
269+
#[doc(inline)]\npub use self::_utils_warp03::*;\n\n",
270270
)?;
271271
}
272272
Ok(Ructe { f, outdir })
@@ -320,7 +320,7 @@ impl Ructe {
320320
///
321321
/// [`StaticFile`]: templates::StaticFile
322322
pub fn statics(&mut self) -> Result<StaticFiles> {
323-
self.f.write_all(b"pub mod statics;")?;
323+
self.f.write_str("pub mod statics;")?;
324324
StaticFiles::for_template_dir(
325325
&self.outdir,
326326
&PathBuf::from(get_env("CARGO_MANIFEST_DIR")?),
@@ -330,27 +330,24 @@ impl Ructe {
330330

331331
impl Drop for Ructe {
332332
fn drop(&mut self) {
333-
let _ = self.f.write_all(b"}\n");
333+
let _ = self.f.write_str("}\n");
334334
let _ =
335335
write_if_changed(&self.outdir.join("../templates.rs"), &self.f);
336336
}
337337
}
338338

339-
fn write_if_changed(path: &Path, content: &[u8]) -> io::Result<()> {
340-
use std::fs::{read, write};
341-
if let Ok(old) = read(path) {
339+
fn write_if_changed(path: &Path, content: &str) -> Result<()> {
340+
use std::fs::{read_to_string, write};
341+
if let Ok(old) = read_to_string(path) {
342342
if old == content {
343343
return Ok(());
344344
}
345345
}
346-
write(path, content)
346+
write(path, content.as_bytes())?;
347+
Ok(())
347348
}
348349

349-
fn handle_entries(
350-
f: &mut impl Write,
351-
indir: &Path,
352-
outdir: &Path,
353-
) -> Result<()> {
350+
fn handle_entries(f: &mut String, indir: &Path, outdir: &Path) -> Result<()> {
354351
println!("cargo:rerun-if-changed={}", indir.display());
355352
for entry in read_dir(indir)? {
356353
let entry = entry?;
@@ -359,11 +356,11 @@ fn handle_entries(
359356
if let Some(filename) = entry.file_name().to_str() {
360357
let outdir = outdir.join(filename);
361358
create_dir_all(&outdir)?;
362-
let mut modrs = Vec::with_capacity(512);
363-
modrs.write_all(
364-
b"#[allow(clippy::useless_attribute, unused)]\n\
365-
use super::{Html,ToHtml};\n",
366-
)?;
359+
let mut modrs = String::with_capacity(512);
360+
modrs.push_str(
361+
"#[allow(clippy::useless_attribute, unused)]\n\
362+
use super::{Html,ToHtml};\n",
363+
);
367364
handle_entries(&mut modrs, &path, &outdir)?;
368365
write_if_changed(&outdir.join("mod.rs"), &modrs)?;
369366
writeln!(f, "pub mod {filename};\n")?;
@@ -391,17 +388,13 @@ fn handle_entries(
391388
Ok(())
392389
}
393390

394-
fn handle_template(
395-
name: &str,
396-
path: &Path,
397-
outdir: &Path,
398-
) -> io::Result<bool> {
391+
fn handle_template(name: &str, path: &Path, outdir: &Path) -> Result<bool> {
399392
let mut input = File::open(path)?;
400393
let mut buf = Vec::new();
401394
input.read_to_end(&mut buf)?;
402395
match template(&buf) {
403396
Ok((_, t)) => {
404-
let mut data = Vec::new();
397+
let mut data = String::new();
405398
t.write_rust(&mut data, name)?;
406399
write_if_changed(
407400
&outdir.join(format!("template_{name}.rs")),
@@ -429,16 +422,19 @@ pub enum RucteError {
429422
Io(io::Error),
430423
/// Error resolving a given environment variable.
431424
Env(String, env::VarError),
432-
/// Error bundling a sass stylesheet as css.
425+
/// A build-time formatting error in Ructe
426+
Fmt(fmt::Error),
433427
#[cfg(feature = "sass")]
428+
/// Error bundling a sass stylesheet as css.
434429
Sass(rsass::Error),
435430
}
436431

437432
impl Error for RucteError {
438433
fn source(&self) -> Option<&(dyn Error + 'static)> {
439434
match &self {
440-
RucteError::Io(e) => Some(e),
441-
RucteError::Env(_, e) => Some(e),
435+
Self::Io(e) => Some(e),
436+
Self::Env(_, e) => Some(e),
437+
Self::Fmt(e) => Some(e),
442438
#[cfg(feature = "sass")]
443439
RucteError::Sass(e) => Some(e),
444440
}
@@ -455,6 +451,7 @@ impl Debug for RucteError {
455451
match self {
456452
RucteError::Io(err) => Display::fmt(err, out),
457453
RucteError::Env(var, err) => write!(out, "{var:?}: {err}"),
454+
Self::Fmt(err) => Display::fmt(err, out),
458455
#[cfg(feature = "sass")]
459456
RucteError::Sass(err) => Debug::fmt(err, out),
460457
}
@@ -466,6 +463,11 @@ impl From<io::Error> for RucteError {
466463
RucteError::Io(e)
467464
}
468465
}
466+
impl From<fmt::Error> for RucteError {
467+
fn from(value: fmt::Error) -> Self {
468+
Self::Fmt(value)
469+
}
470+
}
469471

470472
#[cfg(feature = "sass")]
471473
impl From<rsass::Error> for RucteError {
@@ -475,4 +477,4 @@ impl From<rsass::Error> for RucteError {
475477
}
476478

477479
/// A result where the error type is a [`RucteError`].
478-
pub type Result<T> = std::result::Result<T, RucteError>;
480+
pub type Result<T, E = RucteError> = std::result::Result<T, E>;

src/staticfiles.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use super::Result;
2-
use itertools::Itertools;
32
use std::ascii::escape_default;
43
use std::collections::BTreeMap;
5-
use std::fmt::{self, Display};
4+
use std::fmt::{self, Display, Write};
65
use std::fs::{read_dir, File};
7-
use std::io::{Read, Write};
6+
use std::io::Read;
87
use std::path::{Path, PathBuf};
98

109
/// Handler for static files.
@@ -147,7 +146,7 @@ use std::path::{Path, PathBuf};
147146
/// ```
148147
pub struct StaticFiles {
149148
/// Rust source file `statics.rs` beeing written.
150-
src: Vec<u8>,
149+
src: String,
151150
/// Path for writing the file `statics.rs`.
152151
src_path: PathBuf,
153152
/// Base path for finding static files with relative paths
@@ -163,17 +162,17 @@ impl StaticFiles {
163162
outdir: &Path,
164163
base_path: &Path,
165164
) -> Result<Self> {
166-
let mut src = Vec::with_capacity(512);
165+
let mut src = String::with_capacity(512);
167166
if cfg!(feature = "mime03") {
168-
src.write_all(b"use mime::Mime;\n\n")?;
167+
src.write_str("use mime::Mime;\n\n")?;
169168
}
170169
if cfg!(feature = "tide013") {
171-
src.write_all(b"use tide::http::mime::{self, Mime};\n\n")?;
170+
src.write_str("use tide::http::mime::{self, Mime};\n\n")?;
172171
} else if cfg!(feature = "http-types") {
173-
src.write_all(b"use http_types::mime::{self, Mime};\n\n")?;
172+
src.write_str("use http_types::mime::{self, Mime};\n\n")?;
174173
}
175-
src.write_all(
176-
b"/// A static file has a name (so its url can be recognized) and the
174+
src.write_str(
175+
"/// A static file has a name (so its url can be recognized) and the
177176
/// actual file contents.
178177
///
179178
/// The name includes a short (48 bits as 8 base64 characters) hash of
@@ -185,13 +184,13 @@ pub struct StaticFile {
185184
pub name: &'static str,
186185
")?;
187186
if cfg!(feature = "mime03") {
188-
src.write_all(b" pub mime: &'static Mime,\n")?;
187+
src.write_str(" pub mime: &'static Mime,\n")?;
189188
}
190189
if cfg!(feature = "http-types") {
191-
src.write_all(b" pub mime: &'static Mime,\n")?;
190+
src.write_str(" pub mime: &'static Mime,\n")?;
192191
}
193-
src.write_all(
194-
b"}
192+
src.write_str(
193+
"}
195194
#[allow(dead_code)]
196195
impl StaticFile {
197196
/// Get a single `StaticFile` by name, if it exists.
@@ -520,17 +519,21 @@ impl Drop for StaticFiles {
520519
/// Write the ending of the statics source code, declaring the
521520
/// `STATICS` variable.
522521
fn drop(&mut self) {
522+
fn do_write(s: &mut StaticFiles) -> Result<()> {
523+
write!(s.src, "\npub static STATICS: &[&StaticFile] = &[")?;
524+
let mut q = s.names_r.values();
525+
if let Some(a) = q.next() {
526+
write!(s.src, "&{a}")?;
527+
}
528+
for a in q {
529+
write!(s.src, ", &{a}")?;
530+
}
531+
writeln!(s.src, "];")?;
532+
super::write_if_changed(&s.src_path, &s.src)?;
533+
Ok(())
534+
}
523535
// Ignore a possible write failure, rather than a panic in drop.
524-
let _ = writeln!(
525-
self.src,
526-
"\npub static STATICS: &[&StaticFile] \
527-
= &[{}];",
528-
self.names_r
529-
.iter()
530-
.map(|s| format!("&{}", s.1))
531-
.format(", "),
532-
);
533-
let _ = super::write_if_changed(&self.src_path, &self.src);
536+
let _ = do_write(self);
534537
}
535538
}
536539

src/template.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::expression::{input_to_str, rust_name};
22
use crate::parseresult::PResult;
33
use crate::spacelike::spacelike;
44
use crate::templateexpression::{template_expression, TemplateExpression};
5-
use itertools::Itertools;
65
use nom::branch::alt;
76
use nom::bytes::complete::is_not;
87
use nom::bytes::complete::tag;
@@ -12,7 +11,7 @@ use nom::error::context;
1211
use nom::multi::{many0, many_till, separated_list0, separated_list1};
1312
use nom::sequence::{delimited, preceded, terminated};
1413
use nom::Parser as _;
15-
use std::io::{self, Write};
14+
use std::fmt::Write;
1615

1716
#[derive(Debug, PartialEq, Eq)]
1817
pub struct Template {
@@ -27,9 +26,9 @@ impl Template {
2726
&self,
2827
out: &mut impl Write,
2928
name: &str,
30-
) -> io::Result<()> {
31-
out.write_all(
32-
b"use std::io::{self, Write};\n\
29+
) -> std::fmt::Result {
30+
out.write_str(
31+
"use std::io::{self, Write};\n\
3332
#[allow(clippy::useless_attribute, unused)]\n\
3433
use super::{Html,ToHtml};\n",
3534
)?;
@@ -40,24 +39,32 @@ impl Template {
4039
out,
4140
"\n\
4241
#[allow(clippy::used_underscore_binding)]\n\
43-
pub fn {name}<{ta}{ta_sep}W>(#[allow(unused_mut)] mut _ructe_out_: W{args}) -> io::Result<()>\n\
44-
where W: Write {{\n\
45-
{body}\
46-
Ok(())\n\
47-
}}",
42+
pub fn {name}<{ta}{ta_sep}W>(\
43+
\n #[allow(unused_mut)] mut _ructe_out_: W,",
4844
name = name,
4945
ta = self.type_args,
5046
ta_sep = if self.type_args.is_empty() { "" } else { ", " },
51-
args =
52-
self.args.iter().format_with("", |arg, f| f(&format_args!(
53-
", {}",
54-
arg.replace(
55-
" Content",
56-
" impl FnOnce(&mut W) -> io::Result<()>"
57-
)
58-
))),
59-
body = self.body.iter().map(|b| b.code()).format(""),
60-
)
47+
)?;
48+
for arg in &self.args {
49+
writeln!(
50+
out,
51+
" {},",
52+
arg.replace(
53+
" Content",
54+
" impl FnOnce(&mut W) -> io::Result<()>"
55+
)
56+
)?;
57+
}
58+
writeln!(
59+
out,
60+
") -> io::Result<()>\n\
61+
where W: Write {{",
62+
)?;
63+
for b in &self.body {
64+
b.write_code(out)?;
65+
}
66+
writeln!(out, "Ok(())\n}}")?;
67+
Ok(())
6168
}
6269
}
6370

0 commit comments

Comments
 (0)