use crate::{
build_graph::BuildGraphError,
compile::CompileError,
infrastructure::{CommandError, ConsoleError, DatabaseError, FileError},
ir::Build,
module_dependency::ModuleDependencyError,
parse::ParseError,
};
use alloc::sync::Arc;
use core::{
error::Error,
fmt::{self, Display, Formatter},
};
use tokio::{io, sync::AcquireError, task::JoinError};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum BuildError {
Acquire(String),
Build,
BuildGraph(BuildGraphError),
Command(CommandError),
Compile(CompileError),
Console(ConsoleError),
Database(DatabaseError),
DefaultOutputNotFound(Arc<str>),
DynamicDependencyNotFound(Arc<Build>),
File(FileError),
FileNotFound(String),
InputNotBuilt(String),
InputNotFound(String),
Io(String),
Join(String),
ModuleDependency(ModuleDependencyError),
OutputNotFound(String),
Parse(ParseError),
}
impl Error for BuildError {}
impl Display for BuildError {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match self {
Self::Acquire(message) | Self::Io(message) | Self::Join(message) => {
write!(formatter, "{message}")
}
Self::Build => write!(formatter, "build failed"),
Self::Command(error) => write!(formatter, "{error}"),
Self::Compile(error) => write!(formatter, "{error}"),
Self::Console(error) => write!(formatter, "{error}"),
Self::Database(error) => write!(formatter, "{error}"),
Self::DefaultOutputNotFound(output) => {
write!(formatter, "default output \"{output}\" not found")
}
Self::DynamicDependencyNotFound(build) => {
write!(
formatter,
"outputs {} not found in dynamic dependency file {}",
build.outputs().join(", "),
build.dynamic_module().unwrap()
)
}
Self::File(error) => write!(formatter, "{error}"),
Self::FileNotFound(path) => write!(formatter, "file \"{path}\" not found"),
Self::InputNotBuilt(input) => {
write!(formatter, "input \"{input}\" not built yet")
}
Self::InputNotFound(input) => {
write!(formatter, "input \"{input}\" not found")
}
Self::ModuleDependency(error) => {
write!(formatter, "{error}")
}
Self::OutputNotFound(output) => {
write!(formatter, "output \"{output}\" not found")
}
Self::Parse(error) => write!(formatter, "{error}"),
Self::BuildGraph(error) => write!(formatter, "{error}"),
}
}
}
impl From<AcquireError> for BuildError {
fn from(error: AcquireError) -> Self {
Self::Acquire(error.to_string())
}
}
impl From<CommandError> for BuildError {
fn from(error: CommandError) -> Self {
Self::Command(error)
}
}
impl From<CompileError> for BuildError {
fn from(error: CompileError) -> Self {
Self::Compile(error)
}
}
impl From<ConsoleError> for BuildError {
fn from(error: ConsoleError) -> Self {
Self::Console(error)
}
}
impl From<DatabaseError> for BuildError {
fn from(error: DatabaseError) -> Self {
Self::Database(error)
}
}
impl From<FileError> for BuildError {
fn from(error: FileError) -> Self {
Self::File(error)
}
}
impl From<io::Error> for BuildError {
fn from(error: io::Error) -> Self {
Self::Io(error.to_string())
}
}
impl From<JoinError> for BuildError {
fn from(error: JoinError) -> Self {
Self::Join(error.to_string())
}
}
impl From<ModuleDependencyError> for BuildError {
fn from(error: ModuleDependencyError) -> Self {
Self::ModuleDependency(error)
}
}
impl From<ParseError> for BuildError {
fn from(error: ParseError) -> Self {
Self::Parse(error)
}
}
impl From<BuildGraphError> for BuildError {
fn from(error: BuildGraphError) -> Self {
Self::BuildGraph(error)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_acquire() {
assert_eq!(
BuildError::Acquire("semaphore closed".into()).to_string(),
"semaphore closed"
);
}
#[test]
fn display_io() {
assert_eq!(
BuildError::Io("permission denied".into()).to_string(),
"permission denied"
);
}
#[test]
fn display_join() {
assert_eq!(
BuildError::Join("task cancelled".into()).to_string(),
"task cancelled"
);
}
}