cas_error/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use ariadne::{Color, Report, Source};
4use std::{fmt::Debug, io::Write, ops::Range};
5
6/// The color to use to highlight expressions.
7pub const EXPR: Color = Color::RGB(52, 235, 152);
8
9/// Represents any kind of error that can occur during some operation.
10pub trait ErrorKind: Debug + Send {
11    /// Builds the report for this error.
12    fn build_report<'a>(
13        &self,
14        src_id: &'a str,
15        spans: &[Range<usize>],
16    ) -> Report<(&'a str, Range<usize>)>;
17}
18
19/// An error associated with regions of source code that can be highlighted.
20#[derive(Debug)]
21pub struct Error {
22    /// The regions of the source code that this error originated from.
23    pub spans: Vec<Range<usize>>,
24
25    /// The kind of error that occurred.
26    pub kind: Box<dyn ErrorKind>,
27}
28
29impl Error {
30    /// Creates a new error with the given spans and kind.
31    pub fn new(spans: Vec<Range<usize>>, kind: impl ErrorKind + 'static) -> Self {
32        Self { spans, kind: Box::new(kind) }
33    }
34
35    /// Build a report from this error kind.
36    pub fn build_report<'a>(&self, src_id: &'a str) -> Report<(&'a str, Range<usize>)> {
37        self.kind.build_report(src_id, &self.spans)
38    }
39
40    /// Writes the error to stderr.
41    ///
42    /// The `ariadne` crate's [`Report`] type does not have a `Display` implementation, so we can
43    /// only use its `eprint` method to print to stderr.
44    ///
45    /// [`Report`]: ariadne::Report
46    pub fn report_to_stderr(&self, src_id: &str, input: &str) -> std::io::Result<()> {
47        self.report_to(std::io::stderr(), src_id, input)
48    }
49
50    /// Writes the error to an output stream.
51    pub fn report_to<W: Write>(
52        &self,
53        writer: W,
54        src_id: &str,
55        input: &str,
56    ) -> std::io::Result<()> {
57        let report = self.build_report(src_id);
58        report.write((src_id, Source::from(input)), writer)
59    }
60}