Skip to content

Commit

Permalink
Merge pull request #147 from kaj/iter-strings
Browse files Browse the repository at this point in the history
Get rid of itertools dependency.
  • Loading branch information
kaj authored Feb 6, 2025
2 parents 911c601 + 75ff8c7 commit a749914
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 128 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ project adheres to
## Unreleased

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


Expand Down
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ tide013 = ["http-types"]
[dependencies]
base64 = "0.22.1"
bytecount = "0.6.0"
itertools = "0.14.0"
md5 = "0.7"
nom = "8.0.0"
nom-language = "0.1.0"
Expand Down
80 changes: 41 additions & 39 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ mod templateexpression;
use parseresult::show_errors;
use std::env;
use std::error::Error;
use std::fmt::{self, Debug, Display};
use std::fmt::{self, Debug, Display, Write as _};
use std::fs::{create_dir_all, read_dir, File};
use std::io::{self, Read, Write};
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use template::template;

Expand Down Expand Up @@ -211,7 +211,7 @@ pub use staticfiles::StaticFiles;
///
/// [cargo]: https://doc.rust-lang.org/cargo/
pub struct Ructe {
f: Vec<u8>,
f: String,
outdir: PathBuf,
}

Expand Down Expand Up @@ -241,32 +241,32 @@ impl Ructe {
///
/// [cargo]: https://doc.rust-lang.org/cargo/
pub fn new(outdir: PathBuf) -> Result<Ructe> {
let mut f = Vec::with_capacity(512);
let mut f = String::with_capacity(512);
let outdir = outdir.join("templates");
create_dir_all(&outdir)?;
f.write_all(b"pub mod templates {\n")?;
f.write_str("pub mod templates {\n")?;
write_if_changed(
&outdir.join("_utils.rs"),
include_bytes!(concat!(
include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/templates/utils.rs"
)),
)?;
f.write_all(
b"#[doc(hidden)]\nmod _utils;\n\
#[doc(inline)]\npub use self::_utils::*;\n\n",
f.write_str(
"#[doc(hidden)]\nmod _utils;\n\
#[doc(inline)]\npub use self::_utils::*;\n\n",
)?;
if cfg!(feature = "warp03") {
write_if_changed(
&outdir.join("_utils_warp03.rs"),
include_bytes!(concat!(
include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/templates/utils_warp03.rs"
)),
)?;
f.write_all(
b"#[doc(hidden)]\nmod _utils_warp03;\n\
#[doc(inline)]\npub use self::_utils_warp03::*;\n\n",
f.write_str(
"#[doc(hidden)]\nmod _utils_warp03;\n\
#[doc(inline)]\npub use self::_utils_warp03::*;\n\n",
)?;
}
Ok(Ructe { f, outdir })
Expand Down Expand Up @@ -320,7 +320,7 @@ impl Ructe {
///
/// [`StaticFile`]: templates::StaticFile
pub fn statics(&mut self) -> Result<StaticFiles> {
self.f.write_all(b"pub mod statics;")?;
self.f.write_str("pub mod statics;")?;
StaticFiles::for_template_dir(
&self.outdir,
&PathBuf::from(get_env("CARGO_MANIFEST_DIR")?),
Expand All @@ -330,27 +330,24 @@ impl Ructe {

impl Drop for Ructe {
fn drop(&mut self) {
let _ = self.f.write_all(b"}\n");
let _ = self.f.write_str("}\n");
let _ =
write_if_changed(&self.outdir.join("../templates.rs"), &self.f);
}
}

fn write_if_changed(path: &Path, content: &[u8]) -> io::Result<()> {
use std::fs::{read, write};
if let Ok(old) = read(path) {
fn write_if_changed(path: &Path, content: &str) -> Result<()> {
use std::fs::{read_to_string, write};
if let Ok(old) = read_to_string(path) {
if old == content {
return Ok(());
}
}
write(path, content)
write(path, content.as_bytes())?;
Ok(())
}

fn handle_entries(
f: &mut impl Write,
indir: &Path,
outdir: &Path,
) -> Result<()> {
fn handle_entries(f: &mut String, indir: &Path, outdir: &Path) -> Result<()> {
println!("cargo:rerun-if-changed={}", indir.display());
for entry in read_dir(indir)? {
let entry = entry?;
Expand All @@ -359,11 +356,11 @@ fn handle_entries(
if let Some(filename) = entry.file_name().to_str() {
let outdir = outdir.join(filename);
create_dir_all(&outdir)?;
let mut modrs = Vec::with_capacity(512);
modrs.write_all(
b"#[allow(clippy::useless_attribute, unused)]\n\
use super::{Html,ToHtml};\n",
)?;
let mut modrs = String::with_capacity(512);
modrs.push_str(
"#[allow(clippy::useless_attribute, unused)]\n\
use super::{Html,ToHtml};\n",
);
handle_entries(&mut modrs, &path, &outdir)?;
write_if_changed(&outdir.join("mod.rs"), &modrs)?;
writeln!(f, "pub mod {filename};\n")?;
Expand Down Expand Up @@ -391,17 +388,13 @@ fn handle_entries(
Ok(())
}

fn handle_template(
name: &str,
path: &Path,
outdir: &Path,
) -> io::Result<bool> {
fn handle_template(name: &str, path: &Path, outdir: &Path) -> Result<bool> {
let mut input = File::open(path)?;
let mut buf = Vec::new();
input.read_to_end(&mut buf)?;
match template(&buf) {
Ok((_, t)) => {
let mut data = Vec::new();
let mut data = String::new();
t.write_rust(&mut data, name)?;
write_if_changed(
&outdir.join(format!("template_{name}.rs")),
Expand Down Expand Up @@ -429,16 +422,19 @@ pub enum RucteError {
Io(io::Error),
/// Error resolving a given environment variable.
Env(String, env::VarError),
/// Error bundling a sass stylesheet as css.
/// A build-time formatting error in Ructe
Fmt(fmt::Error),
#[cfg(feature = "sass")]
/// Error bundling a sass stylesheet as css.
Sass(rsass::Error),
}

impl Error for RucteError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self {
RucteError::Io(e) => Some(e),
RucteError::Env(_, e) => Some(e),
Self::Io(e) => Some(e),
Self::Env(_, e) => Some(e),
Self::Fmt(e) => Some(e),
#[cfg(feature = "sass")]
RucteError::Sass(e) => Some(e),
}
Expand All @@ -455,6 +451,7 @@ impl Debug for RucteError {
match self {
RucteError::Io(err) => Display::fmt(err, out),
RucteError::Env(var, err) => write!(out, "{var:?}: {err}"),
Self::Fmt(err) => Display::fmt(err, out),
#[cfg(feature = "sass")]
RucteError::Sass(err) => Debug::fmt(err, out),
}
Expand All @@ -466,6 +463,11 @@ impl From<io::Error> for RucteError {
RucteError::Io(e)
}
}
impl From<fmt::Error> for RucteError {
fn from(value: fmt::Error) -> Self {
Self::Fmt(value)
}
}

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

/// A result where the error type is a [`RucteError`].
pub type Result<T> = std::result::Result<T, RucteError>;
pub type Result<T, E = RucteError> = std::result::Result<T, E>;
51 changes: 27 additions & 24 deletions src/staticfiles.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use super::Result;
use itertools::Itertools;
use std::ascii::escape_default;
use std::collections::BTreeMap;
use std::fmt::{self, Display};
use std::fmt::{self, Display, Write};
use std::fs::{read_dir, File};
use std::io::{Read, Write};
use std::io::Read;
use std::path::{Path, PathBuf};

/// Handler for static files.
Expand Down Expand Up @@ -147,7 +146,7 @@ use std::path::{Path, PathBuf};
/// ```
pub struct StaticFiles {
/// Rust source file `statics.rs` beeing written.
src: Vec<u8>,
src: String,
/// Path for writing the file `statics.rs`.
src_path: PathBuf,
/// Base path for finding static files with relative paths
Expand All @@ -163,17 +162,17 @@ impl StaticFiles {
outdir: &Path,
base_path: &Path,
) -> Result<Self> {
let mut src = Vec::with_capacity(512);
let mut src = String::with_capacity(512);
if cfg!(feature = "mime03") {
src.write_all(b"use mime::Mime;\n\n")?;
src.write_str("use mime::Mime;\n\n")?;
}
if cfg!(feature = "tide013") {
src.write_all(b"use tide::http::mime::{self, Mime};\n\n")?;
src.write_str("use tide::http::mime::{self, Mime};\n\n")?;
} else if cfg!(feature = "http-types") {
src.write_all(b"use http_types::mime::{self, Mime};\n\n")?;
src.write_str("use http_types::mime::{self, Mime};\n\n")?;
}
src.write_all(
b"/// A static file has a name (so its url can be recognized) and the
src.write_str(
"/// A static file has a name (so its url can be recognized) and the
/// actual file contents.
///
/// The name includes a short (48 bits as 8 base64 characters) hash of
Expand All @@ -185,13 +184,13 @@ pub struct StaticFile {
pub name: &'static str,
")?;
if cfg!(feature = "mime03") {
src.write_all(b" pub mime: &'static Mime,\n")?;
src.write_str(" pub mime: &'static Mime,\n")?;
}
if cfg!(feature = "http-types") {
src.write_all(b" pub mime: &'static Mime,\n")?;
src.write_str(" pub mime: &'static Mime,\n")?;
}
src.write_all(
b"}
src.write_str(
"}
#[allow(dead_code)]
impl StaticFile {
/// Get a single `StaticFile` by name, if it exists.
Expand Down Expand Up @@ -520,17 +519,21 @@ impl Drop for StaticFiles {
/// Write the ending of the statics source code, declaring the
/// `STATICS` variable.
fn drop(&mut self) {
fn do_write(s: &mut StaticFiles) -> Result<()> {
write!(s.src, "\npub static STATICS: &[&StaticFile] = &[")?;
let mut q = s.names_r.values();
if let Some(a) = q.next() {
write!(s.src, "&{a}")?;
}
for a in q {
write!(s.src, ", &{a}")?;
}
writeln!(s.src, "];")?;
super::write_if_changed(&s.src_path, &s.src)?;
Ok(())
}
// Ignore a possible write failure, rather than a panic in drop.
let _ = writeln!(
self.src,
"\npub static STATICS: &[&StaticFile] \
= &[{}];",
self.names_r
.iter()
.map(|s| format!("&{}", s.1))
.format(", "),
);
let _ = super::write_if_changed(&self.src_path, &self.src);
let _ = do_write(self);
}
}

Expand Down
47 changes: 27 additions & 20 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::expression::{input_to_str, rust_name};
use crate::parseresult::PResult;
use crate::spacelike::spacelike;
use crate::templateexpression::{template_expression, TemplateExpression};
use itertools::Itertools;
use nom::branch::alt;
use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
Expand All @@ -12,7 +11,7 @@ use nom::error::context;
use nom::multi::{many0, many_till, separated_list0, separated_list1};
use nom::sequence::{delimited, preceded, terminated};
use nom::Parser as _;
use std::io::{self, Write};
use std::fmt::Write;

#[derive(Debug, PartialEq, Eq)]
pub struct Template {
Expand All @@ -27,9 +26,9 @@ impl Template {
&self,
out: &mut impl Write,
name: &str,
) -> io::Result<()> {
out.write_all(
b"use std::io::{self, Write};\n\
) -> std::fmt::Result {
out.write_str(
"use std::io::{self, Write};\n\
#[allow(clippy::useless_attribute, unused)]\n\
use super::{Html,ToHtml};\n",
)?;
Expand All @@ -40,24 +39,32 @@ impl Template {
out,
"\n\
#[allow(clippy::used_underscore_binding)]\n\
pub fn {name}<{ta}{ta_sep}W>(#[allow(unused_mut)] mut _ructe_out_: W{args}) -> io::Result<()>\n\
where W: Write {{\n\
{body}\
Ok(())\n\
}}",
pub fn {name}<{ta}{ta_sep}W>(\
\n #[allow(unused_mut)] mut _ructe_out_: W,",
name = name,
ta = self.type_args,
ta_sep = if self.type_args.is_empty() { "" } else { ", " },
args =
self.args.iter().format_with("", |arg, f| f(&format_args!(
", {}",
arg.replace(
" Content",
" impl FnOnce(&mut W) -> io::Result<()>"
)
))),
body = self.body.iter().map(|b| b.code()).format(""),
)
)?;
for arg in &self.args {
writeln!(
out,
" {},",
arg.replace(
" Content",
" impl FnOnce(&mut W) -> io::Result<()>"
)
)?;
}
writeln!(
out,
") -> io::Result<()>\n\
where W: Write {{",
)?;
for b in &self.body {
b.write_code(out)?;
}
writeln!(out, "Ok(())\n}}")?;
Ok(())
}
}

Expand Down
Loading

0 comments on commit a749914

Please sign in to comment.