/ src / zkas / error.rs
error.rs
 1  /* This file is part of DarkFi (https://dark.fi)
 2   *
 3   * Copyright (C) 2020-2025 Dyne.org foundation
 4   *
 5   * This program is free software: you can redistribute it and/or modify
 6   * it under the terms of the GNU Affero General Public License as
 7   * published by the Free Software Foundation, either version 3 of the
 8   * License, or (at your option) any later version.
 9   *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Affero General Public License for more details.
14   *
15   * You should have received a copy of the GNU Affero General Public License
16   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17   */
18  
19  use std::io::{self, Error, Write};
20  
21  pub(super) struct ErrorEmitter {
22      namespace: String,
23      file: String,
24      lines: Vec<String>,
25  }
26  
27  impl ErrorEmitter {
28      pub fn new(namespace: &str, file: &str, lines: Vec<String>) -> Self {
29          Self { namespace: namespace.to_string(), file: file.to_string(), lines }
30      }
31  
32      fn fmt(&self, msg: String, ln: usize, col: usize) -> String {
33          let (err_msg, dbg_msg, caret) = match ln {
34              0 => (msg, "".to_string(), "".to_string()),
35              _ => {
36                  let err_msg = format!("{msg} (line {ln}, column {col})");
37                  let dbg_msg = format!("{}:{ln}:{col}: {}", self.file, self.lines[ln - 1]);
38                  let pad = dbg_msg.split(": ").next().unwrap().len() + col + 1;
39                  let caret = format!("{:width$}^", "", width = pad);
40                  (err_msg, dbg_msg, caret)
41              }
42          };
43          format!("{err_msg}\n{dbg_msg}\n{caret}\n")
44      }
45  
46      pub fn abort(&self, msg: &str, ln: usize, col: usize) -> Error {
47          let m = self.fmt(msg.to_string(), ln, col);
48          self.emit("error", &m);
49          Error::other(m)
50      }
51  
52      pub fn warn(&self, msg: &str, ln: usize, col: usize) {
53          let m = self.fmt(msg.to_string(), ln, col);
54          self.emit("warning", &m);
55      }
56  
57      pub fn emit(&self, typ: &str, msg: &str) {
58          if std::env::var("ZKAS_SILENT").is_ok() {
59              return
60          }
61  
62          let stderr = io::stderr();
63          let mut handle = stderr.lock();
64  
65          match typ {
66              "error" => write!(handle, "\x1b[31;1m{} error:\x1b[0m {msg}", self.namespace).unwrap(),
67  
68              "warning" => {
69                  write!(handle, "\x1b[33;1m{} warning:\x1b[0m {msg}", self.namespace).unwrap()
70              }
71  
72              _ => unreachable!(),
73          };
74  
75          handle.flush().unwrap();
76      }
77  }