1use std::fmt;
11use std::os::raw::c_int;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct AvError(c_int);
21
22impl AvError {
23 #[must_use]
25 pub const fn new(code: c_int) -> Self {
26 Self(code)
27 }
28
29 #[must_use]
31 pub const fn code(self) -> c_int {
32 self.0
33 }
34
35 #[must_use]
38 pub const fn is_eagain(self) -> bool {
39 self.0 == crate::error_codes::EAGAIN
40 }
41
42 #[must_use]
45 pub const fn is_eof(self) -> bool {
46 self.0 == crate::error_codes::EOF
47 }
48}
49
50impl fmt::Display for AvError {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 write!(f, "{} (code={})", crate::av_error_string(self.0), self.0)
53 }
54}
55
56impl std::error::Error for AvError {}
57
58impl From<c_int> for AvError {
59 fn from(code: c_int) -> Self {
60 Self(code)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn av_error_should_preserve_the_raw_code() {
70 assert_eq!(AvError::new(-22).code(), -22);
71 }
72
73 #[test]
74 fn av_error_should_detect_eagain() {
75 assert!(AvError::new(crate::error_codes::EAGAIN).is_eagain());
76 assert!(!AvError::new(crate::error_codes::EOF).is_eagain());
77 }
78
79 #[test]
80 fn av_error_should_detect_eof() {
81 assert!(AvError::new(crate::error_codes::EOF).is_eof());
82 assert!(!AvError::new(crate::error_codes::EAGAIN).is_eof());
83 }
84
85 #[test]
86 fn av_error_display_should_include_the_message_and_code() {
87 let rendered = AvError::new(crate::error_codes::EOF).to_string();
88 assert!(
89 rendered.contains("code="),
90 "display should include the raw code: {rendered}"
91 );
92 assert!(!rendered.is_empty());
93 }
94
95 #[test]
96 fn av_error_should_convert_from_a_raw_code() {
97 let err = AvError::from(-22);
98 assert_eq!(err.code(), -22);
99 }
100}