1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! # error
//!
//! The error structure and types.
//!

use crate::types::instruction::InstructionMetaInfo;
use fsio::error::FsIOError;
use std::fmt;
use std::fmt::Display;

#[cfg(test)]
#[path = "./error_test.rs"]
mod error_test;

fn format_error_message(
    formatter: &mut fmt::Formatter,
    meta_info: &InstructionMetaInfo,
    message: &str,
) -> Result<(), fmt::Error> {
    let source = match meta_info.source {
        Some(ref value) => value.to_string(),
        None => "Unknown".to_string(),
    };
    let line = match meta_info.line {
        Some(value) => value.to_string(),
        None => "Unknown".to_string(),
    };

    write!(formatter, "Source: {} Line: {} - {}", source, line, message)
}

#[derive(Debug)]
/// Holds the error information
pub enum ErrorInfo {
    /// Error Info Type
    ErrorReadingFile(String, Option<FsIOError>),
    /// Error Info Type
    Initialization(String),
    /// Error Info Type
    Runtime(String, Option<InstructionMetaInfo>),
    /// Error Info Type
    PreProcessNoCommandFound(InstructionMetaInfo),
    /// Error Info Type
    ControlWithoutValidValue(InstructionMetaInfo),
    /// Error Info Type
    InvalidControlLocation(InstructionMetaInfo),
    /// Error Info Type
    MissingEndQuotes(InstructionMetaInfo),
    /// Error Info Type
    MissingOutputVariableName(InstructionMetaInfo),
    /// Error Info Type
    InvalidEqualsLocation(InstructionMetaInfo),
    /// Error Info Type
    InvalidQuotesLocation(InstructionMetaInfo),
    /// Error Info Type
    EmptyLabel(InstructionMetaInfo),
    /// Error Info Type
    UnknownPreProcessorCommand(InstructionMetaInfo),
}

#[derive(Debug)]
/// Script error struct
pub struct ScriptError {
    /// Holds the error information
    pub info: ErrorInfo,
}

impl Display for ScriptError {
    /// Formats the script error using the given formatter.
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.info {
            ErrorInfo::ErrorReadingFile(ref file, ref cause) => {
                writeln!(formatter, "Error reading file: {}", file)?;
                match cause {
                    Some(cause_err) => cause_err.fmt(formatter),
                    None => Ok(()),
                }
            }
            ErrorInfo::Initialization(ref message) => write!(formatter, "{}", message),
            ErrorInfo::Runtime(ref message, ref meta_info) => {
                let empty_meta_data = InstructionMetaInfo::new();
                let meta_info_value = meta_info.as_ref().unwrap_or(&empty_meta_data);
                format_error_message(formatter, &meta_info_value, message)
            }
            ErrorInfo::PreProcessNoCommandFound(ref meta_info) => {
                format_error_message(formatter, &meta_info, "preprocessor is missing a command")
            }
            ErrorInfo::ControlWithoutValidValue(ref meta_info) => format_error_message(
                formatter,
                &meta_info,
                "control character found without a valid value",
            ),
            ErrorInfo::InvalidControlLocation(ref meta_info) => {
                format_error_message(formatter, &meta_info, "invalid control character location")
            }
            ErrorInfo::MissingEndQuotes(ref meta_info) => {
                format_error_message(formatter, &meta_info, "missing end quotes")
            }
            ErrorInfo::MissingOutputVariableName(ref meta_info) => {
                format_error_message(formatter, &meta_info, "missing variable name")
            }
            ErrorInfo::InvalidEqualsLocation(ref meta_info) => {
                format_error_message(formatter, &meta_info, "invalid equals sign location")
            }
            ErrorInfo::InvalidQuotesLocation(ref meta_info) => {
                format_error_message(formatter, &meta_info, "invalid quotes location")
            }
            ErrorInfo::EmptyLabel(ref meta_info) => {
                format_error_message(formatter, &meta_info, "empty lable found")
            }
            ErrorInfo::UnknownPreProcessorCommand(ref meta_info) => {
                format_error_message(formatter, &meta_info, "unknow preprocessor command")
            }
        }
    }
}