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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use std::error;
use std::fmt;
use std::io::Error as ioError;

#[derive(Debug)]
/// Represents potential errors that may occur when profiling
pub enum ProfError {
    RegexError,
    InvalidProfiler,
    InvalidBinary,
    InvalidNum,
    InvalidSortMetric,
    /// Wraps a std::io::Error
    IOError(ioError),
    UTF8Error,
    MisalignedData,
    CompilationError(String, String),
    TomlError,
    ReadManifestError,
    NoNameError,
    NoTargetDirectory,
    OutOfMemoryError,
    CliError,
}

impl fmt::Display for ProfError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ProfError::RegexError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mRegex error -- please file a bug. In bug report, \
                        please include the original output file from profiler, e.g. from \
                        valgrind --tool=cachegrind --cachegrind-out-file=cachegrind.txt")
            }
            ProfError::InvalidProfiler => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mInvalid profiler. cargo profiler currently \
                        supports callgrind and cachegrind.")
            }
            ProfError::InvalidBinary => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mInvalid binary. make sure binary exists.")
            }
            ProfError::InvalidNum => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mInvalid number. make sure number is a positive \
                        integer.")
            }
            ProfError::InvalidSortMetric => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mInvalid metric to sort on. available cachegrind \
                        metrics are \nir, i1mr, ilmr, dr, d1mr, dlmr, dw, d1mw, and dlmw. Check \
                        README for details on these metrics.")
            }
            ProfError::IOError(ref err) => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mIO error: {} -- please file a bug.",
                       err)
            }
            ProfError::UTF8Error => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mCLI Utf8 error -- please file a bug.")
            }
            ProfError::MisalignedData => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mMisaligned data arrays due to regex error -- \
                        please file a bug.")
            }
            ProfError::CompilationError(ref package_name, ref stderr) => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mFailed to compile {}.\n\n{}",
                       package_name,
                       stderr)
            }
            ProfError::TomlError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mError in parsing Cargo.toml to derive package \
                        name. Make sure package name is directly under [package] tag.")
            }
            ProfError::ReadManifestError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mCargo.toml missing. Are you sure you're in a Rust \
                        project?")
            }

            ProfError::NoNameError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mNo package name found in Cargo.toml. Run \
                        cargo read-manifest to make sure everything looks okay. Otherwise please \
                        submit bug.")
            }

            ProfError::NoTargetDirectory => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mNo target output directory found in project. \
                        Binary must be in target/debug/ or target/release/, or specify binary \
                        path explicitly with --bin argument.")
            }
            ProfError::OutOfMemoryError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mValgrind's memory management: out of memory. \
                        Valgrind cannot continue. Sorry. ")
            }
            ProfError::CliError => {
                write!(f,
                       "\x1b[1;31merror: \x1b[0mError in valgrind cli call. Make sure valgrind is \
                        installed properly.")
            }
        }
    }
}

impl error::Error for ProfError {
    fn description(&self) -> &str {
        match *self {
            ProfError::RegexError => "Regex error. file bug.",
            ProfError::InvalidProfiler => "Invalid Profiler.",
            ProfError::InvalidBinary => "Invalid Binary.",
            ProfError::InvalidNum => "Invalid number.",
            ProfError::InvalidSortMetric => "Invalid sort metric.",
            ProfError::MisalignedData => "Misaligned Data. File bug.",
            ProfError::CompilationError(_, _) => {
                "Failed to compile. Run cargo build to get compilation error."
            }
            ProfError::TomlError => "Error in parsing Cargo.toml.",
            ProfError::ReadManifestError => "Error in reading the manifest of this crate.",
            ProfError::NoNameError => "No package name found in Cargo.toml",
            ProfError::NoTargetDirectory => "No target output directory found in project.",
            ProfError::IOError(ref err) => err.description(),
            ProfError::OutOfMemoryError => "out of memory.",
            ProfError::CliError => "make sure valgrind is installed properly.",
            ProfError::UTF8Error => "utf8 error. file bug.",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ProfError::RegexError => None,
            ProfError::InvalidProfiler => None,
            ProfError::InvalidBinary => None,
            ProfError::InvalidNum => None,
            ProfError::InvalidSortMetric => None,
            ProfError::MisalignedData => None,
            ProfError::TomlError => None,
            ProfError::IOError(ref err) => Some(err),
            ProfError::CompilationError(_, _) => None,
            ProfError::ReadManifestError => None,
            ProfError::NoNameError => None,
            ProfError::NoTargetDirectory => None,
            ProfError::OutOfMemoryError => None,
            ProfError::CliError => None,
            ProfError::UTF8Error => None,
        }
    }
}

impl From<ioError> for ProfError {
    fn from(err: ioError) -> ProfError {
        ProfError::IOError(err)
    }
}