1use std::io;
4
5use audio_core_bsd::AudioError;
6
7#[derive(Debug, thiserror::Error)]
20pub enum ClockError {
21 #[error("clock source unavailable: {0}")]
24 Unavailable(String),
25
26 #[error("clock not yet synchronised: {0}")]
29 NotSynced(String),
30
31 #[error("invalid sample rate: {0} Hz")]
33 InvalidSampleRate(u32),
34
35 #[error("timestamp conversion overflow")]
40 ConversionOverflow,
41
42 #[error(transparent)]
44 Core(#[from] AudioError),
45
46 #[error(transparent)]
48 Io(#[from] io::Error),
49}
50
51pub type Result<T> = core::result::Result<T, ClockError>;
53
54#[cfg(test)]
55mod tests {
56 use std::io;
57
58 use audio_core_bsd::AudioError;
59
60 use super::{ClockError, Result};
61
62 #[test]
63 fn unavailable_display_carries_message() {
64 let msg = ClockError::Unavailable("no ptpd".into()).to_string();
65 assert_eq!(msg, "clock source unavailable: no ptpd");
66 }
67
68 #[test]
69 fn not_synced_display_carries_message() {
70 let msg = ClockError::NotSynced("ntp converging".into()).to_string();
71 assert_eq!(msg, "clock not yet synchronised: ntp converging");
72 }
73
74 #[test]
75 fn invalid_sample_rate_display_includes_value() {
76 let msg = ClockError::InvalidSampleRate(0).to_string();
77 assert_eq!(msg, "invalid sample rate: 0 Hz");
78 }
79
80 #[test]
81 fn conversion_overflow_display() {
82 assert_eq!(
83 ClockError::ConversionOverflow.to_string(),
84 "timestamp conversion overflow"
85 );
86 }
87
88 #[test]
89 fn core_variant_wraps_audio_error() {
90 let err = ClockError::from(AudioError::InvalidSampleRate(0));
91 assert_eq!(err.to_string(), "invalid sample rate: 0 Hz");
92 }
93
94 #[test]
95 fn core_from_audio_error_preserves_identity() {
96 let core = AudioError::InvalidChannelCount(0);
97 let wrapped: ClockError = core.clone().into();
98 assert!(matches!(wrapped, ClockError::Core(ref e) if *e == core));
99 }
100
101 #[test]
102 fn io_variant_wraps_std_io_error() {
103 let io_err = io::Error::new(io::ErrorKind::NotFound, "missing");
104 let err = ClockError::from(io_err);
105 assert!(err.to_string().contains("missing"));
106 }
107
108 #[test]
109 fn result_alias_ok_carries_value() {
110 let ok: Result<u32> = Ok(7);
111 assert_eq!(ok.map(|v| v + 1).unwrap(), 8);
112 }
113
114 #[test]
115 fn result_alias_err_carries_clock_error() {
116 let err: Result<u32> = Err(ClockError::Unavailable("x".into()));
117 assert!(err.is_err());
118 }
119}