Skip to main content

harn_vm/stdlib/template/
error.rs

1use std::path::PathBuf;
2
3use crate::value::{VmError, VmValue};
4
5#[derive(Debug, Clone)]
6pub(crate) struct TemplateError {
7    pub path: Option<PathBuf>,
8    pub uri: Option<String>,
9    pub line: usize,
10    pub col: usize,
11    pub kind: String,
12}
13
14impl TemplateError {
15    pub(crate) fn new(line: usize, col: usize, msg: impl Into<String>) -> Self {
16        Self {
17            path: None,
18            uri: None,
19            line,
20            col,
21            kind: msg.into(),
22        }
23    }
24
25    pub(crate) fn message(&self) -> String {
26        let p = self
27            .path
28            .as_ref()
29            .map(|p| format!("{} ", p.display()))
30            .or_else(|| self.uri.as_ref().map(|uri| format!("{uri} ")))
31            .unwrap_or_default();
32        format!("{}at {}:{}: {}", p, self.line, self.col, self.kind)
33    }
34}
35
36impl From<TemplateError> for VmError {
37    fn from(e: TemplateError) -> Self {
38        VmError::Thrown(VmValue::String(arcstr::ArcStr::from(e.message())))
39    }
40}
41
42/// A template that failed to parse, positioned in its own source.
43///
44/// The engine's internal error also carries the asset path/URI it came
45/// from, which is meaningless to a caller that handed us a source
46/// string. This is the projection tools get: what went wrong and where,
47/// as data rather than as a pre-formatted sentence, so `harn lint` and
48/// the language server can each place the diagnostic their own way.
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub struct TemplateParseError {
51    /// What went wrong, with no position prefix.
52    pub message: String,
53    /// 1-based line of the directive that failed to parse.
54    pub line: usize,
55    /// 1-based column of that directive.
56    pub col: usize,
57}
58
59impl From<TemplateError> for TemplateParseError {
60    fn from(error: TemplateError) -> Self {
61        Self {
62            message: error.kind,
63            line: error.line,
64            col: error.col,
65        }
66    }
67}
68
69impl std::fmt::Display for TemplateParseError {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        write!(f, "at {}:{}: {}", self.line, self.col, self.message)
72    }
73}
74
75impl std::error::Error for TemplateParseError {}