psrutils/
error.rs

1//! Errors enum.
2#![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    // Par errors ---------------------------------
12    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    // Tim errors ---------------------------------
39    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}