/ manager / src / error.rs
error.rs
  1  use std::io;
  2  use std::path::{Path, PathBuf};
  3  use thiserror::Error;
  4  
  5  #[derive(Default)]
  6  pub struct Errors {
  7      errors: Vec<Error>,
  8  }
  9  
 10  pub struct Error {
 11      location: PathBuf,
 12      inner: InnerError,
 13  }
 14  
 15  #[derive(Debug, Error)]
 16  pub enum InnerError {
 17      #[error("IO Error: {0}")]
 18      IoErr(#[from] io::Error),
 19  
 20      #[error("Failed to parse template file")]
 21      TemplateErr(#[from] blueprint::Error),
 22  
 23      #[error("Failed to parse toml file")]
 24      TomlErr(#[from] toml::de::Error),
 25  
 26      #[error("Unsupported variable type")]
 27      TypeErr,
 28  }
 29  
 30  impl From<Vec<Error>> for Errors {
 31      fn from(errors: Vec<Error>) -> Self {
 32          Errors { errors }
 33      }
 34  }
 35  
 36  impl<E> From<E> for Errors
 37  where
 38      E: Into<Error>,
 39  {
 40      fn from(error: E) -> Self {
 41          Errors {
 42              errors: vec![error.into()],
 43          }
 44      }
 45  }
 46  
 47  impl Errors {
 48      pub fn join(&mut self, mut other: Errors) {
 49          self.errors.append(&mut other.errors);
 50      }
 51  
 52      pub fn is_empty(&self) -> bool {
 53          self.errors.is_empty()
 54      }
 55  
 56      pub fn log(self) {
 57          if self.errors.is_empty() {
 58              return;
 59          }
 60  
 61          error!("{} errors occured:", self.errors.len());
 62          for (i, error) in self.errors.iter().enumerate() {
 63              error!("  err {:02} at {:?}:", i, error.location);
 64              error!("      {}", error.inner);
 65          }
 66      }
 67  }
 68  
 69  pub trait ErrorLocation {
 70      type Err;
 71      fn with_location(self, path: &Path) -> Self::Err;
 72  }
 73  
 74  impl<T> ErrorLocation for T
 75  where
 76      T: Into<InnerError>,
 77  {
 78      type Err = Error;
 79  
 80      fn with_location(self, path: &Path) -> Error {
 81          Error {
 82              location: path.to_owned(),
 83              inner: self.into(),
 84          }
 85      }
 86  }
 87  
 88  impl<T, E> ErrorLocation for Result<T, E>
 89  where
 90      E: Into<InnerError>,
 91  {
 92      type Err = Result<T, Error>;
 93  
 94      fn with_location(self, path: &Path) -> Result<T, Error> {
 95          self.map_err(|e| Error {
 96              location: path.to_owned(),
 97              inner: e.into(),
 98          })
 99      }
100  }