use crate::error::Builder;
use crate::vm::Exception;
use std::convert::Infallible;
use std::fmt::{self, Display, Formatter};
use std::num::NonZero;
use std::io;
use std::process::{ExitCode, Termination};
#[derive(Clone, Debug)]
pub struct Error {
message: Box<str>,
offset: Option<NonZero<u64>>,
}
impl Error {
#[must_use]
pub(super) fn from_builder(builder: Builder) -> Self {
let message = builder.message
.expect("missing error message");
let offset = builder.offset;
Self { message, offset }
}
#[inline]
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
#[inline]
#[must_use]
pub fn offset(&self) -> Option<u64> {
self.offset
.map(|o| o.get() - 1)
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "\u{001B}[001m\u{001B}[091merror\u{001B}[039m\u{001B}[022m: {}\u{001B}[022m", self.message())?;
if let Some(offset) = self.offset() {
writeln!(f, "\u{001B}[001m\u{001B}[096m note\u{001B}[039m\u{001B}[022m: at offset `{offset:#X}`")?;
}
Ok(())
}
}
impl std::error::Error for Error {}
impl From<io::Error> for Error {
fn from(value: io::Error) -> Self {
Builder::new()
.message(value)
.build()
}
}
impl From<Exception> for Error {
fn from(value: Exception) -> Self {
Builder::new()
.message(value)
.build()
}
}
impl From<Infallible> for Error {
#[inline(always)]
fn from(value: Infallible) -> Self {
match value {}
}
}
impl Termination for Error {
fn report(self) -> ExitCode {
1_u8.into()
}
}