1use core::fmt;
9
10#[derive(Debug, Clone, Eq, PartialEq)]
12pub enum CoreError {
13 TooShort { have: usize, need: usize },
15 BadMagic { found: [u8; 4] },
17 Corrupt { reason: String },
20 UnsupportedFeature { feature: String },
24}
25
26impl fmt::Display for CoreError {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Self::TooShort { have, need } => {
30 write!(
31 f,
32 "manifest header truncated: have {have} bytes, need {need}"
33 )
34 }
35 Self::BadMagic { found } => write!(
36 f,
37 "bad manifest magic: expected LMFS ({:x?}), found {:?} ({:x?})",
38 *b"LMFS",
39 core::str::from_utf8(found).unwrap_or("<non-utf8>"),
40 found
41 ),
42 Self::Corrupt { reason } => write!(f, "manifest corrupt: {reason}"),
43 Self::UnsupportedFeature { feature } => {
44 write!(f, "unsupported feature: {feature}")
45 }
46 }
47 }
48}
49
50impl std::error::Error for CoreError {}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn display_covers_every_variant() {
58 let cases = [
59 (
60 CoreError::TooShort { have: 4, need: 16 },
61 vec!["truncated", "16"],
62 ),
63 (
64 CoreError::BadMagic { found: *b"XXXX" },
65 vec!["LMFS", "XXXX"],
66 ),
67 (
68 CoreError::Corrupt {
69 reason: "broken".into(),
70 },
71 vec!["corrupt", "broken"],
72 ),
73 (
74 CoreError::UnsupportedFeature {
75 feature: "feature_flags section version 7".into(),
76 },
77 vec!["unsupported", "version 7"],
78 ),
79 ];
80 for (error, needles) in cases {
81 let s = error.to_string();
82 for needle in needles {
83 assert!(s.contains(needle), "display {s:?} missing {needle:?}");
84 }
85 }
86 }
87
88 #[test]
89 fn variants_are_eq_comparable() {
90 assert_eq!(
91 CoreError::TooShort { have: 4, need: 5 },
92 CoreError::TooShort { have: 4, need: 5 }
93 );
94 assert_ne!(
95 CoreError::TooShort { have: 4, need: 5 },
96 CoreError::TooShort { have: 4, need: 6 }
97 );
98 }
99}