Skip to main content

argos_arpa/
error.rs

1use std::{path::PathBuf, process::Output, string::FromUtf8Error};
2
3use crate::archivist::ArchivistError;
4
5#[derive(Debug)]
6#[allow(missing_docs)]
7pub enum ARPAError {
8    TokioJoinError(tokio::task::JoinError),
9    IOFault(std::io::Error),
10    Psrutils(psrutils::error::PsruError),
11    // TimFile(psrutils::timfile::TimError),
12    // J2000Parse(psrutils::error::J2000ParseError),
13    ToolFailure(String, Output),
14    JoinThread(String),
15    ConfigLoadFailure(toml::de::Error),
16    ConfigSaveFailure(toml::ser::Error),
17    MissingFileOrDirectory(PathBuf),
18    StringConversion(Vec<u8>),
19    ArchivistError(ArchivistError),
20
21    MalformedInput(String),
22    ParseFailed(String, &'static str),
23    ChecksumFail(String),
24
25    CantFind(String),
26
27    ChefNoEphemeride,
28    ChefNoTemplate,
29    ChefNoRaw,
30    MissingEphemeride(i32),
31    VapKeyCount(usize, usize),
32
33    UnknownDiagnostic(String),
34    DiagnosticPlotBadFile(String),
35    TOAExpectedFormat(String),
36    MissingPsrchive(String),
37}
38
39impl std::error::Error for ARPAError {}
40
41impl std::fmt::Display for ARPAError {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        match self {
44            Self::TokioJoinError(error) => write!(f, "[tokio] {error}",),
45            Self::IOFault(error) => write!(f, "[std::io] {error}",),
46            Self::Psrutils(error) => write!(f, "[psrutils] {error}",),
47            // Self::TimFile(error) => write!(f, "[psrutils::tim] {error}"),
48            // Self::J2000Parse(error) => write!(f, "[psrutils::J2000] {error}"),
49            Self::ToolFailure(tool, out) => write!(
50                f,
51                "Tool \"{}\" failed{}\n-- stdout:\n{}\n-- stderr:\n{}",
52                tool,
53                out.status.code().map_or_else(
54                    || "(codeless)".into(),
55                    |c| format!("(code: {c})")
56                ),
57                String::from_utf8_lossy(&out.stdout),
58                String::from_utf8_lossy(&out.stderr),
59            ),
60            Self::JoinThread(msg) => write!(
61                f,
62                "One of your threads was unable to join, saying: \"{msg}\"",
63            ),
64            Self::ConfigLoadFailure(err) => {
65                write!(f, "Encountered error reading config file: {err}",)
66            }
67            Self::ConfigSaveFailure(err) => {
68                write!(f, "Encountered error writing config file: {err}",)
69            }
70            Self::MissingFileOrDirectory(path) => {
71                write!(
72                    f,
73                    "File or directory \"{}\" is missing.",
74                    path.display()
75                )
76            }
77            Self::StringConversion(bytes) => {
78                write!(f, "Failed to parse string from bytes: {bytes:?}",)
79            }
80            Self::ArchivistError(err) => {
81                write!(f, "Archivist failed action.\n{err}")
82            }
83
84            Self::MalformedInput(comment) => {
85                write!(f, "Malformed input: {comment}.",)
86            }
87            Self::ParseFailed(data, type_) => {
88                write!(f, "Failed to parse \"{data}\" as {type_}",)
89            }
90            Self::ChecksumFail(file) => {
91                write!(f, "Checksum falied for file \"{file}\".",)
92            }
93
94            Self::CantFind(thing) => write!(f, "Could not find {thing}.",),
95
96            Self::ChefNoRaw => {
97                write!(f, "Somehow we got here without a rawfile...")
98            }
99            Self::ChefNoEphemeride => {
100                write!(f, "Cannot build chef without ephemeride.")
101            }
102            Self::ChefNoTemplate => {
103                write!(f, "Cannot build chef without template.")
104            }
105            Self::MissingEphemeride(id) => write!(
106                f,
107                "Pulsar with id {id} has no master parfile set, but it was \
108                required by the pipeline."
109            ),
110            Self::VapKeyCount(keys, values) => write!(
111                f,
112                "Psrchive::vap was asked for {keys} values but returned \
113                {values}.",
114            ),
115
116            Self::UnknownDiagnostic(dia) => {
117                write!(f, "\"{dia}\" is not a recognised diagnostic tool.",)
118            }
119            Self::DiagnosticPlotBadFile(file) => {
120                write!(f, "Can't figure out what you want to plot from {file}.",)
121            }
122            Self::TOAExpectedFormat(line) => write!(
123                f,
124                "Expected \"FORMAT 1\" from psrchive::pat, but got \"{line}\".",
125            ),
126            Self::MissingPsrchive(tool) => write!(
127                f,
128                "psrchive::{tool} could not be run. \
129                Please check your installation or the path supplied in \
130                config.toml."
131            ),
132        }
133    }
134}
135
136impl From<tokio::task::JoinError> for ARPAError {
137    fn from(value: tokio::task::JoinError) -> Self {
138        Self::TokioJoinError(value)
139    }
140}
141impl From<std::io::Error> for ARPAError {
142    fn from(value: std::io::Error) -> Self {
143        Self::IOFault(value)
144    }
145}
146// impl From<psrutils::error::TimError> for ARPAError {
147//     fn from(value: psrutils::error::TimError) -> Self {
148//         Self::TimFile(value)
149//     }
150// }
151// impl From<psrutils::error::J2000ParseError> for ARPAError {
152//     fn from(value: psrutils::error::J2000ParseError) -> Self {
153//         Self::J2000Parse(value)
154//     }
155// }
156impl From<psrutils::error::PsruError> for ARPAError {
157    fn from(value: psrutils::error::PsruError) -> Self {
158        Self::Psrutils(value)
159    }
160}
161impl From<FromUtf8Error> for ARPAError {
162    fn from(value: FromUtf8Error) -> Self {
163        Self::StringConversion(value.into_bytes())
164    }
165}
166impl From<toml::de::Error> for ARPAError {
167    fn from(value: toml::de::Error) -> Self {
168        Self::ConfigLoadFailure(value)
169    }
170}
171impl From<toml::ser::Error> for ARPAError {
172    fn from(value: toml::ser::Error) -> Self {
173        Self::ConfigSaveFailure(value)
174    }
175}
176impl From<ArchivistError> for ARPAError {
177    fn from(value: ArchivistError) -> Self {
178        Self::ArchivistError(value)
179    }
180}