1#![allow(missing_docs)]
3
4use std::error::Error;
5
6#[derive(Debug)]
7pub enum PsruError {
8 Unparsable{ value: String, to_type: &'static str },
9 IOError(std::io::Error),
10
11 InvalidRA(String),
13 InvalidDec(String),
14 ParMissingValue(String),
15
16 ParUnknownFlag(String),
17 ParUnrecognisedKey(String),
18 UnknownBinaryModel(String),
19 UnknownTimeEphemeris(String),
20 UnknownT2CMethod(String),
21 UnknownUnits(String),
22 UnknownErrorMode(String),
23
24 IncompleteJump(String),
25 BadGlitch(usize),
26
27 ParNoName,
28 ParNoFrequency,
29 ParNoPEpoch,
30 ParNoDispersion,
31
32 ParBadFrequency,
33 ParBadPEpoch,
34
35 ParDuplicateParameters(Vec<(String, String)>),
36 ParRepeatParam(String),
37
38 TimUnexpectedEOL(Option<TimContext>),
40 TimMalformedMJD(Option<TimContext>),
41 TimUnvaluedFlag(Option<TimContext>, String),
42 TimFormatDiscrepancy(Option<TimContext>, String),
43 TimNotAscii(Option<TimContext>),
44 TimParkesMissingBlank(Option<TimContext>),
45 TimParkesMissingPeriod(Option<TimContext>),
46}
47impl std::fmt::Display for PsruError {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 PsruError::Unparsable { value, to_type }
51 => write!(f, "Impossible to parse '{}' into type {}.", value, to_type),
52 PsruError::IOError(error)
53 => write!(f, "IO error >> {}", error),
54
55 PsruError::InvalidRA(ra)
56 => write!(f, "Invalid RA string '{}'.", ra),
57 PsruError::InvalidDec(dec)
58 => write!(f, "Invalid DEC string '{}'.", dec),
59 PsruError::ParMissingValue(p)
60 => write!(f, "Param '{}' missing value.", p),
61
62 PsruError::ParUnknownFlag(flag)
63 => write!(f, "Unknown flag '{}'.", flag),
64 PsruError::ParUnrecognisedKey(k)
65 => write!(f, "Unrecognised key '{}'.", k),
66 PsruError::UnknownBinaryModel(m)
67 => write!(f, "Unknown binary model '{}'.", m),
68 PsruError::UnknownTimeEphemeris(te)
69 => write!(f, "Unknown time ephemeris '{}'.", te),
70 PsruError::UnknownT2CMethod(t2cm)
71 => write!(f, "Unknown t2CMethod '{}'.", t2cm),
72 PsruError::UnknownErrorMode(em)
73 => write!(f, "Unknown error mode '{}'.", em),
74 PsruError::UnknownUnits(u)
75 => write!(f, "Unknown units '{}'.", u),
76
77 PsruError::IncompleteJump(j)
78 => write!(f, "Incomplete jump '{}'.", j),
79 PsruError::BadGlitch(g)
80 => write!(f, "Glitch with index {} is incomplete.", g),
81
82 PsruError::ParNoName
83 => write!(f, "Missing PSR parameter."),
84 PsruError::ParNoFrequency
85 => write!(f, "Missing F0 parameter."),
86 PsruError::ParNoPEpoch
87 => write!(f, "Missing PEPOCH parameter."),
88 PsruError::ParNoDispersion
89 => write!(f, "Missing DM parameter."),
90
91 PsruError::ParBadPEpoch
92 => write!(f, "Bad PEPOCH parameter."),
93 PsruError::ParBadFrequency
94 => write!(f, "Bad F0 parameter."),
95
96 PsruError::ParDuplicateParameters(items)
97 => write!(
98 f, "There are duplicate parameters defined:{}",
99 items
100 .iter()
101 .fold(String::new(), |a, (l1, l2)|
102 format!("{}\n * '{}' and '{}'", a, l1, l2))
103 ),
104
105 PsruError::ParRepeatParam(param)
106 => write!(f, "Repeated '{}' parameter.", param),
107
108 PsruError::TimUnexpectedEOL(ctx) => write!(f,
109 "{} TOA line ended prematurely",
110 tim_ctx(ctx)),
111 PsruError::TimMalformedMJD(ctx) => write!(f,
112 "{} MJD is expected to be in decimal format.",
113 tim_ctx(ctx)),
114 PsruError::TimUnvaluedFlag(ctx, flag) => write!(f,
115 "{} Flag '{}' did not have a value.",
116 tim_ctx(ctx), flag),
117 PsruError::TimFormatDiscrepancy(ctx, fmt) => write!(f,
118 "{} Read format does not match supplied '{}'",
119 tim_ctx(ctx), fmt),
120 PsruError::TimNotAscii(ctx) => write!(f,
121 "{} Cannot handle non-ascii text in the supplied mode.",
122 tim_ctx(ctx)),
123 PsruError::TimParkesMissingBlank(ctx) => write!(f,
124 "{} There's supposed to be a blank space in the first column.",
125 tim_ctx(ctx)),
126 PsruError::TimParkesMissingPeriod(ctx) => write!(f,
127 "{} There's supposed to be a period in the column 42.",
128 tim_ctx(ctx)),
129 }
130 }
131}
132impl PsruError {
133 pub(crate) fn set_tim_ctx(mut self, ctx: &TimContext) -> PsruError {
134 let old_ctx = match &mut self {
135 PsruError::TimUnexpectedEOL(ctx) => ctx,
136 PsruError::TimMalformedMJD(ctx) => ctx,
137 PsruError::TimUnvaluedFlag(ctx, _) => ctx,
138 PsruError::TimFormatDiscrepancy(ctx, _) => ctx,
139 PsruError::TimNotAscii(ctx) => ctx,
140 _ => return self,
141 };
142
143 if old_ctx.is_none() {
144 *old_ctx = Some(ctx.clone());
145 }
146
147 self
148 }
149}
150impl Error for PsruError {}
151
152#[derive(Debug, Clone)]
153pub struct TimContext {
154 fname: String,
155 line: usize,
156}
157impl TimContext {
158 pub(crate) fn new(fname: &str, line_number: usize) -> Self {
159 Self { fname: fname.to_string(), line: line_number }
160 }
161 pub(crate) fn line(&mut self, number: usize) {
162 self.line = number;
163 }
164}
165impl std::fmt::Display for TimContext {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 write!(f, "In file '{}' on line {}:", self.fname, self.line)
168 }
169}
170
171fn tim_ctx(ctx: &Option<TimContext>) -> String {
172 match ctx {
173 Some(ctx) => ctx.to_string(),
174 None => String::new(),
175 }
176}