Skip to main content

fits_header/
error.rs

1//! Error type for fallible header operations.
2
3/// A `Result` whose error is always [`FitsError`].
4pub type Result<T> = std::result::Result<T, FitsError>;
5
6/// Errors from validated header mutations, ambiguous lookups, and oversized standalone
7/// serialization.
8///
9/// Parsing is lenient and does not produce these; header-only serialization
10/// ([`Header::to_header_bytes`](crate::Header::to_header_bytes)) is infallible.
11///
12/// # Examples
13///
14/// ```
15/// # use fits_header::{FitsError, Header};
16/// let mut h = Header::new();
17/// h.append("GAIN", 1).unwrap();
18/// h.append("GAIN", 2).unwrap();
19/// assert!(matches!(
20///     h.get::<i64>("GAIN"),
21///     Err(FitsError::AmbiguousKeyword { .. })
22/// ));
23/// ```
24#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
25#[non_exhaustive]
26pub enum FitsError {
27    /// A bare-name `get`/`set`/`remove` addressed a keyword that occurs more than once.
28    /// Select one with an `(name, occurrence)` key.
29    #[error("keyword '{keyword}' occurs {count} times; select an occurrence")]
30    AmbiguousKeyword {
31        /// The duplicated keyword.
32        keyword: String,
33        /// How many times it occurs.
34        count: usize,
35    },
36
37    /// A keyword longer than the 8-character FITS field.
38    #[error("keyword '{keyword}' exceeds 8 characters")]
39    KeywordTooLong {
40        /// The offending keyword.
41        keyword: String,
42    },
43
44    /// A keyword containing bytes outside the FITS keyword set (`A-Z 0-9 - _`).
45    #[error("keyword '{keyword}' contains characters outside A-Z 0-9 - _")]
46    InvalidKeyword {
47        /// The offending keyword.
48        keyword: String,
49    },
50
51    /// An `(name, occurrence)` key targeted an occurrence that does not exist.
52    #[error("keyword '{keyword}' has no occurrence {occurrence} (found {count})")]
53    OccurrenceOutOfRange {
54        /// The keyword addressed.
55        keyword: String,
56        /// The 0-based occurrence requested.
57        occurrence: usize,
58        /// How many occurrences exist.
59        count: usize,
60    },
61
62    /// [`Header::update_file`](crate::Header::update_file) found no `END` card in the
63    /// existing file's header region, so the data unit's boundary cannot be located.
64    #[error("no END card found in header")]
65    MissingEnd,
66
67    /// [`Header::update_file`](crate::Header::update_file) found an `END` card, but the file
68    /// ends before that header's 2880-byte block is complete — a truncated FITS file.
69    #[error("header ends before its 2880-byte block is complete (truncated file)")]
70    TruncatedHeader,
71
72    /// A file read or write failed ([`Header::read_from_file`](crate::Header::read_from_file),
73    /// [`Header::update_file`](crate::Header::update_file)).
74    #[error("I/O error: {0}")]
75    Io(String),
76}
77
78impl From<std::io::Error> for FitsError {
79    fn from(e: std::io::Error) -> Self {
80        FitsError::Io(e.to_string())
81    }
82}