1use arcbox_error::CommonError;
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, VirtioError>;
8
9#[derive(Debug, Error)]
11pub enum VirtioError {
12 #[error(transparent)]
14 Common(#[from] CommonError),
15
16 #[error("device not ready: {0}")]
18 NotReady(String),
19
20 #[error("invalid queue configuration: {0}")]
22 InvalidQueue(String),
23
24 #[error("invalid descriptor: {0}")]
26 InvalidDescriptor(String),
27
28 #[error("buffer too small: need {needed}, got {got}")]
30 BufferTooSmall { needed: usize, got: usize },
31
32 #[error("I/O error: {0}")]
34 Io(String),
35
36 #[error("memory error: {0}")]
38 MemoryError(String),
39
40 #[error("{device} error: {message}")]
42 DeviceError { device: String, message: String },
43
44 #[error("feature not supported: {0}")]
46 FeatureNotSupported(String),
47
48 #[error("operation not supported: {0}")]
50 NotSupported(String),
51
52 #[error("invalid operation: {0}")]
54 InvalidOperation(String),
55}
56
57impl From<std::io::Error> for VirtioError {
59 fn from(err: std::io::Error) -> Self {
60 Self::Common(CommonError::from(err))
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_not_ready_error() {
70 let err = VirtioError::NotReady("device not initialized".to_string());
71 assert!(err.to_string().contains("device not ready"));
72 assert!(err.to_string().contains("device not initialized"));
73 }
74
75 #[test]
76 fn test_invalid_queue_error() {
77 let err = VirtioError::InvalidQueue("size must be power of 2".to_string());
78 assert!(err.to_string().contains("invalid queue"));
79 }
80
81 #[test]
82 fn test_invalid_descriptor_error() {
83 let err = VirtioError::InvalidDescriptor("out of bounds".to_string());
84 assert!(err.to_string().contains("invalid descriptor"));
85 }
86
87 #[test]
88 fn test_buffer_too_small_error() {
89 let err = VirtioError::BufferTooSmall {
90 needed: 1024,
91 got: 512,
92 };
93 let msg = err.to_string();
94 assert!(msg.contains("1024"));
95 assert!(msg.contains("512"));
96 }
97
98 #[test]
99 fn test_io_error() {
100 let err = VirtioError::Io("read failed".to_string());
101 assert!(err.to_string().contains("I/O error"));
102 }
103
104 #[test]
105 fn test_io_error_from_std() {
106 let std_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
107 let err: VirtioError = std_err.into();
108 assert!(err.to_string().contains("file not found"));
109 }
110
111 #[test]
112 fn test_memory_error() {
113 let err = VirtioError::MemoryError("allocation failed".to_string());
114 assert!(err.to_string().contains("memory error"));
115 }
116
117 #[test]
118 fn test_device_error() {
119 let err = VirtioError::DeviceError {
120 device: "block".to_string(),
121 message: "disk full".to_string(),
122 };
123 let msg = err.to_string();
124 assert!(msg.contains("block"));
125 assert!(msg.contains("disk full"));
126 }
127
128 #[test]
129 fn test_feature_not_supported() {
130 let err = VirtioError::FeatureNotSupported("multiqueue".to_string());
131 assert!(err.to_string().contains("feature not supported"));
132 }
133
134 #[test]
135 fn test_not_supported_error() {
136 let err = VirtioError::NotSupported("flush".to_string());
137 assert!(err.to_string().contains("operation not supported"));
138 }
139
140 #[test]
141 fn test_invalid_operation_error() {
142 let err = VirtioError::InvalidOperation("write to read-only".to_string());
143 assert!(err.to_string().contains("invalid operation"));
144 }
145
146 #[test]
147 fn test_error_debug() {
148 let err = VirtioError::NotReady("test".to_string());
149 let debug_str = format!("{:?}", err);
150 assert!(debug_str.contains("NotReady"));
151 }
152
153 #[test]
154 fn test_result_type_alias() {
155 fn returns_ok() -> Result<u32> {
156 Ok(42)
157 }
158
159 fn returns_err() -> Result<u32> {
160 Err(VirtioError::NotReady("test".to_string()))
161 }
162
163 assert!(returns_ok().is_ok());
164 assert!(returns_err().is_err());
165 }
166}