gtmpl 0.7.1

The Golang Templating Language for Rust
Documentation
use crate::node::{ChainNode, CommandNode, Nodes, PipeNode};
use gtmpl_value::{FuncError, Value};
use std::{fmt, num::ParseIntError, string::FromUtf8Error};
use thiserror::Error;

#[derive(Debug)]
pub struct ErrorContext {
    pub name: String,
    pub line: usize,
}

impl fmt::Display for ErrorContext {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}", self.name, self.line)
    }
}

#[derive(Error, Debug)]
pub enum ParseError {
    #[error("unexpected {0} in define clause")]
    UnexpectedInDefineClause(Nodes),
    #[error("unexpected end")]
    UnexpectedEnd,
    #[error("template: {0}:{1}")]
    WithContext(ErrorContext, String),
    #[error("no tree")]
    NoTree,
    #[error(transparent)]
    NodeError(#[from] NodeError),
    #[error("enable gtmpl_dynamic_template to use a pipeline as name")]
    NoDynamicTemplate,
    #[error("unable to parse string: {0}")]
    UnableToParseString(String),
}

impl ParseError {
    pub fn with_context(name: impl ToString, line: usize, msg: impl ToString) -> Self {
        Self::WithContext(
            ErrorContext {
                name: name.to_string(),
                line,
            },
            msg.to_string(),
        )
    }
}

#[derive(Error, Debug)]
pub enum NodeError {
    #[error("unable to unquote")]
    UnquoteError,
    #[error("NaN")]
    NaN,
    #[error("not a tree node")]
    NaTN,
}

#[derive(Error, Debug)]
pub enum PrintError {
    #[error("unable to process verb: {0}")]
    UnableToProcessVerb(String),
    #[error("{0:X} is not a valid char")]
    NotAValidChar(i128),
    #[error("unable to format {0} as {1}")]
    UnableToFormat(Value, char),
    #[error("unable to terminate format arg: {0}")]
    UnableToTerminateFormatArg(String),
    #[error("missing ] in {0}")]
    MissingClosingBracket(String),
    #[error("unable to parse index: {0}")]
    UnableToParseIndex(ParseIntError),
    #[error("unable to parse width: {0}")]
    UnableToParseWidth(ParseIntError),
    #[error("width after index (e.g. %[3]2d)")]
    WithAfterIndex,
    #[error("precision after index (e.g. %[3].2d)")]
    PrecisionAfterIndex,
}

#[derive(Error, Debug)]
pub enum ExecError {
    #[error("{0} is an incomplete or empty template")]
    IncompleteTemplate(String),
    #[error("{0}")]
    IOError(#[from] std::io::Error),
    #[error("unknown node: {0}")]
    UnknownNode(Nodes),
    #[error("expected if or with node, got {0}")]
    ExpectedIfOrWith(Nodes),
    #[error("unable to convert output to uft-8: {0}")]
    Utf8ConversionFailed(FromUtf8Error),
    #[error("empty var stack")]
    EmptyStack,
    #[error("var context smaller than {0}")]
    VarContextToSmall(usize),
    #[error("invalid range {0:?}")]
    InvalidRange(Value),
    #[error("pipeline must yield a String")]
    PipelineMustYieldString,
    #[error("template {0} not defined")]
    TemplateNotDefined(String),
    #[error("exceeded max template depth")]
    MaxTemplateDepth,
    #[error("error evaluating pipe: {0}")]
    ErrorEvaluatingPipe(PipeNode),
    #[error("no arguments for command node: {0}")]
    NoArgsForCommandNode(CommandNode),
    #[error("cannot evaluate command: {0}")]
    CannotEvaluateCommand(Nodes),
    #[error("field chain without fields :/")]
    FieldChainWithoutFields,
    #[error("{0} has arguments but cannot be invoked as function")]
    NotAFunctionButArguments(String),
    #[error("no fields in eval_chain_node")]
    NoFieldsInEvalChainNode,
    #[error("indirection through explicit nul in {0}")]
    NullInChain(ChainNode),
    #[error("cannot handle {0} as argument")]
    InvalidArgument(Nodes),
    #[error("{0} is not a defined function")]
    UndefinedFunction(String),
    #[error(transparent)]
    FuncError(#[from] FuncError),
    #[error("can't give argument to non-function {0}")]
    ArgumentForNonFunction(Nodes),
    #[error("only maps and objects have fields")]
    OnlyMapsAndObjectsHaveFields,
    #[error("no field {0} for {1}")]
    NoFiledFor(String, Value),
    #[error("variable {0} not found")]
    VariableNotFound(String),
}

#[derive(Error, Debug)]
pub enum TemplateError {
    #[error(transparent)]
    ExecError(#[from] ExecError),
    #[error(transparent)]
    ParseError(#[from] ParseError),
}