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 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::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}
146impl 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}