Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ cache:
- target

rust:
- 1.16.0
- 1.17.0
- 1.46.0
- stable
- nightly
- beta
Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ description = "Rust implementation of Mustache"
repository = "https://github.com/nickel-org/rust-mustache"
documentation = "http://nickel-org.github.io/rust-mustache"
version = "0.9.0"
autotests = false
edition = "2021"
authors = ["erick.tryzelaar@gmail.com"]
license = "MIT/Apache-2.0"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ git push --tags origin master
[1]: http://code.google.com/p/google-ctemplate/
[2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
[3]: https://mustache.github.io/
[4]: http://mustache.github.com/mustache.5.html
[4]: https://mustache.github.io/mustache.5.html
[5]: https://docs.rs/mustache

# License
Expand Down
13 changes: 11 additions & 2 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use std::string::ToString;
use std::collections::HashMap;
use serde::Serialize;

use encoder::Error;
use crate::encoder::Error;
use super::{Data, to_data};

/// `MapBuilder` is a helper type that construct `Data` types.
#[derive(Default)]
#[derive(Default, Debug)]
pub struct MapBuilder {
data: HashMap<String, Data>,
}
Expand Down Expand Up @@ -149,6 +149,15 @@ impl MapBuilder {
data.insert(key.to_string(), Data::Fun(RefCell::new(Box::new(f))));
MapBuilder { data: data }
}
#[inline]
pub fn insert_fn2<K: ToString, F>(self, key: K, f: F) -> MapBuilder
where
F: FnMut(String, &mut dyn FnMut(String) -> String) -> String + Send + 'static,
{
let MapBuilder { mut data } = self;
data.insert(key.to_string(), Data::Fun2(RefCell::new(Box::new(f))));
MapBuilder { data: data }
}

/// Return the built `Data`.
#[inline]
Expand Down
16 changes: 8 additions & 8 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::io::ErrorKind::NotFound;
use std::io::Read;
use std::fs::File;

use parser::{Parser, Token};
use crate::parser::{Parser, Token};
use super::Context;

use Result;
use crate::Result;

pub type PartialsMap = HashMap<String, Vec<Token>>;

Expand Down Expand Up @@ -51,7 +51,7 @@ impl<T: Iterator<Item = char>> Compiler<T> {
pub fn compile(mut self) -> Result<(Vec<Token>, PartialsMap)> {
let (tokens, partials) = {
let parser = Parser::new(&mut self.reader, &self.otag, &self.ctag);
try!(parser.parse())
parser.parse()?
};

// Compile the partials if we haven't done so already.
Expand All @@ -66,7 +66,7 @@ impl<T: Iterator<Item = char>> Compiler<T> {
match File::open(&path) {
Ok(mut file) => {
let mut string = String::new();
try!(file.read_to_string(&mut string));
file.read_to_string(&mut string)?;

let compiler = Compiler {
ctx: self.ctx.clone(),
Expand All @@ -76,7 +76,7 @@ impl<T: Iterator<Item = char>> Compiler<T> {
ctag: "}}".to_string(),
};

let (tokens, subpartials) = try!(compiler.compile());
let (tokens, subpartials) = compiler.compile()?;

// Include subpartials
self.partials.extend(subpartials.into_iter());
Expand All @@ -101,9 +101,9 @@ impl<T: Iterator<Item = char>> Compiler<T> {
mod tests {
use std::path::PathBuf;

use parser::Token;
use compiler::Compiler;
use context::Context;
use crate::parser::Token;
use crate::compiler::Compiler;
use crate::context::Context;

fn compile_str(template: &str) -> Vec<Token> {
let ctx = Context::new(PathBuf::from("."));
Expand Down
14 changes: 7 additions & 7 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use template::{self, Template};
use compiler;
use {Result, Error};
use crate::template::{self, Template};
use crate::compiler;
use crate::{Result, Error};

use std::fmt;
use std::fs::File;
Expand Down Expand Up @@ -37,7 +37,7 @@ impl Context {
/// Compiles a template from a string
pub fn compile<IT: Iterator<Item = char>>(&self, reader: IT) -> Result<Template> {
let compiler = compiler::Compiler::new(self.clone(), reader);
let (tokens, partials) = try!(compiler.compile());
let (tokens, partials) = compiler.compile()?;

Ok(template::new(self.clone(), tokens, partials))
}
Expand All @@ -49,8 +49,8 @@ impl Context {
let mut path = self.template_path.join(path.as_ref());
path.set_extension(&self.template_extension);
let mut s = vec![];
let mut file = try!(File::open(&path));
try!(file.read_to_end(&mut s));
let mut file = File::open(&path)?;
file.read_to_end(&mut s)?;

// TODO: maybe allow UTF-16 as well?
let template = match str::from_utf8(&*s) {
Expand All @@ -62,4 +62,4 @@ impl Context {

self.compile(template.chars())
}
}
}
14 changes: 11 additions & 3 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ use std::collections::HashMap;
use std::cell::RefCell;
use std::fmt;

// for bug!
use log::{log, error};

pub enum Data {
Null,
String(String),
Bool(bool),
Vec(Vec<Data>),
Map(HashMap<String, Data>),
Fun(RefCell<Box<FnMut(String) -> String + Send>>),
Fun(RefCell<Box<dyn FnMut(String) -> String + Send>>),
Fun2(RefCell<Box<dyn FnMut(String, &mut dyn FnMut(String) -> String) -> String + Send>>),
}

impl PartialEq for Data {
Expand All @@ -20,7 +24,10 @@ impl PartialEq for Data {
(&Data::Bool(ref v0), &Data::Bool(ref v1)) => v0 == v1,
(&Data::Vec(ref v0), &Data::Vec(ref v1)) => v0 == v1,
(&Data::Map(ref v0), &Data::Map(ref v1)) => v0 == v1,
(&Data::Fun(_), &Data::Fun(_)) => bug!("Cannot compare closures"),
(&Data::Fun(_), &Data::Fun(_)) => {
bug!("Cannot compare closures");
false
},
(_, _) => false,
}
}
Expand All @@ -35,6 +42,7 @@ impl fmt::Debug for Data {
Data::Vec(ref v) => write!(f, "VecVal({:?})", v),
Data::Map(ref v) => write!(f, "Map({:?})", v),
Data::Fun(_) => write!(f, "Fun(...)"),
Data::Fun2(_) => write!(f, "Fun2(...)"),
}
}
}
}
30 changes: 12 additions & 18 deletions src/encoder.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::error;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::result;
use std::result::Result as StdResult;

use serde::{self, Serialize, ser};

Expand Down Expand Up @@ -31,29 +31,24 @@ impl serde::ser::Error for Error {
}

/// Alias for a `Result` with the error type `mustache::encoder::Error`.
pub type Result<T> = result::Result<T, Error>;
pub type Result<T> = StdResult<T, Error>;

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::error::Error;
self.description().fmt(f)
}
}

impl error::Error for Error {
fn description(&self) -> &str {
match *self {
write!(f, "{}", match *self {
Error::NestedOptions => "nested Option types are not supported",
Error::UnsupportedType => "unsupported type",
Error::MissingElements => "no elements in value",
Error::KeyIsNotString => "key is not a string",
Error::NoDataToEncode => "the encodable type created no data",
Error::Message(ref s) => s,
Error::__Nonexhaustive => unreachable!(),
}
})
}
}

impl StdError for Error { }

#[derive(Default)]
pub struct Encoder;

Expand Down Expand Up @@ -328,7 +323,7 @@ impl ser::SerializeTupleVariant for SerializeTupleVariant {
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()>
where T: Serialize
{
self.vec.push(try!(to_data(&value)));
self.vec.push(to_data(&value)?);
Ok(())
}

Expand Down Expand Up @@ -362,11 +357,10 @@ impl ser::SerializeMap for SerializeMap {
where
T: Serialize
{
let key = self.next_key.take();
// Panic because this indicates a bug in the program rather than an
// expected failure.
let key = key.expect("serialize_value called before serialize_key");
self.map.insert(key, try!(to_data(&value)));
// Taking the key should only fail if this gets called before
// serialize_key, which is a bug in the library.
let key = self.next_key.take().ok_or(Error::MissingElements)?;
self.map.insert(key, to_data(&value)?);
Ok(())
}

Expand Down
31 changes: 13 additions & 18 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as StdIoError;
use std::result;
use std::result::Result as StdResult;

use parser;
use encoder;
use crate::parser;
use crate::encoder;

/// Error type for any error within this library.
///
Expand All @@ -14,6 +13,7 @@ use encoder;
pub enum Error {
InvalidStr,
NoFilename,
IncompleteSection,
Io(StdIoError),
Parser(parser::Error),
Encoder(encoder::Error),
Expand All @@ -22,24 +22,19 @@ pub enum Error {
__Nonexhaustive,
}

pub type Result<T> = result::Result<T, Error>;
pub type Result<T> = StdResult<T, Error>;

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}

impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidStr => "invalid str",
Error::NoFilename => "a filename must be provided",
Error::Io(ref err) => err.description(),
Error::Parser(ref err) => err.description(),
Error::Encoder(ref err) => err.description(),
write!(f, "{}", match *self {
Error::InvalidStr => "invalid str".to_string(),
Error::NoFilename => "a filename must be provided".to_string(),
Error::IncompleteSection => "a section wasn't completed".to_string(), // Is there a better way to put this?
Error::Io(ref err) => err.to_string(),
Error::Parser(ref err) => err.to_string(),
Error::Encoder(ref err) => err.to_string(),
Error::__Nonexhaustive => unreachable!(),
}
})
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/// This should be the only place to panic inside non-test code.
// TODO: ensure no panics elsewhere via clippy
macro_rules! bug {
($msg:expr) => ({
bug!("{}", $msg)
});
($fmt:expr, $($arg:tt)+) => ({
panic!(
error!(
concat!("bug: ",
$fmt,
". Please report this issue on GitHub if you find \
Expand Down
Loading