go_template/
error.rs

1use crate::node::{ChainNode, CommandNode, Nodes, PipeNode};
2use gtmpl_value::{FuncError, Value};
3use std::{fmt, num::ParseIntError, string::FromUtf8Error};
4use thiserror::Error;
5
6#[derive(Debug)]
7pub struct ErrorContext {
8    pub name: String,
9    pub line: usize,
10}
11
12impl fmt::Display for ErrorContext {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        write!(f, "{}:{}", self.name, self.line)
15    }
16}
17
18#[derive(Error, Debug)]
19pub enum ParseError {
20    #[error("unexpected {0} in define clause")]
21    UnexpectedInDefineClause(Nodes),
22    #[error("unexpected end")]
23    UnexpectedEnd,
24    #[error("template: {0}:{1}")]
25    WithContext(ErrorContext, String),
26    #[error("no tree")]
27    NoTree,
28    #[error(transparent)]
29    NodeError(#[from] NodeError),
30    #[error("enable gtmpl_dynamic_template to use a pipeline as name")]
31    NoDynamicTemplate,
32    #[error("unable to parse string: {0}")]
33    UnableToParseString(String),
34}
35
36impl ParseError {
37    pub fn with_context(name: impl ToString, line: usize, msg: impl ToString) -> Self {
38        Self::WithContext(
39            ErrorContext {
40                name: name.to_string(),
41                line,
42            },
43            msg.to_string(),
44        )
45    }
46}
47
48#[derive(Error, Debug)]
49pub enum NodeError {
50    #[error("unable to unquote")]
51    UnquoteError,
52    #[error("NaN")]
53    NaN,
54    #[error("not a tree node")]
55    NaTN,
56}
57
58#[derive(Error, Debug)]
59pub enum PrintError {
60    #[error("unable to process verb: {0}")]
61    UnableToProcessVerb(String),
62    #[error("{0:X} is not a valid char")]
63    NotAValidChar(i128),
64    #[error("unable to format {0} as {1}")]
65    UnableToFormat(Value, char),
66    #[error("unable to terminate format arg: {0}")]
67    UnableToTerminateFormatArg(String),
68    #[error("missing ] in {0}")]
69    MissingClosingBracket(String),
70    #[error("unable to parse index: {0}")]
71    UnableToParseIndex(ParseIntError),
72    #[error("unable to parse width: {0}")]
73    UnableToParseWidth(ParseIntError),
74    #[error("width after index (e.g. %[3]2d)")]
75    WithAfterIndex,
76    #[error("precision after index (e.g. %[3].2d)")]
77    PrecisionAfterIndex,
78}
79
80#[derive(Error, Debug)]
81pub enum ExecError {
82    #[error("{0} is an incomplete or empty template")]
83    IncompleteTemplate(String),
84    #[error("{0}")]
85    IOError(#[from] std::io::Error),
86    #[error("unknown node: {0}")]
87    UnknownNode(Nodes),
88    #[error("expected if or with node, got {0}")]
89    ExpectedIfOrWith(Nodes),
90    #[error("unable to convert output to uft-8: {0}")]
91    Utf8ConversionFailed(FromUtf8Error),
92    #[error("empty var stack")]
93    EmptyStack,
94    #[error("var context smaller than {0}")]
95    VarContextToSmall(usize),
96    #[error("invalid range {0:?}")]
97    InvalidRange(Value),
98    #[error("pipeline must yield a String")]
99    PipelineMustYieldString,
100    #[error("template {0} not defined")]
101    TemplateNotDefined(String),
102    #[error("exceeded max template depth")]
103    MaxTemplateDepth,
104    #[error("error evaluating pipe: {0}")]
105    ErrorEvaluatingPipe(PipeNode),
106    #[error("no arguments for command node: {0}")]
107    NoArgsForCommandNode(CommandNode),
108    #[error("cannot evaluate command: {0}")]
109    CannotEvaluateCommand(Nodes),
110    #[error("field chain without fields :/")]
111    FieldChainWithoutFields,
112    #[error("{0} has arguments but cannot be invoked as function")]
113    NotAFunctionButArguments(String),
114    #[error("no fields in eval_chain_node")]
115    NoFieldsInEvalChainNode,
116    #[error("indirection through explicit nul in {0}")]
117    NullInChain(ChainNode),
118    #[error("cannot handle {0} as argument")]
119    InvalidArgument(Nodes),
120    #[error("{0} is not a defined function")]
121    UndefinedFunction(String),
122    #[error(transparent)]
123    FuncError(#[from] FuncError),
124    #[error("can't give argument to non-function {0}")]
125    ArgumentForNonFunction(Nodes),
126    #[error("only maps and objects have fields")]
127    OnlyMapsAndObjectsHaveFields,
128    #[error("no field {0} for {1}")]
129    NoFiledFor(String, Value),
130    #[error("variable {0} not found")]
131    VariableNotFound(String),
132}
133
134#[derive(Error, Debug)]
135pub enum TemplateError {
136    #[error(transparent)]
137    ExecError(#[from] ExecError),
138    #[error(transparent)]
139    ParseError(#[from] ParseError),
140}