1use std::fmt;
7use std::sync::Arc;
8
9#[derive(Debug, Clone)]
14pub enum AsyncError {
15 Initialization {
17 component: Arc<str>,
18 message: Arc<str>,
19 recoverable: bool,
20 },
21
22 TaskTracking {
24 operation: TaskOperation,
25 message: Arc<str>,
26 task_id: Option<crate::async_memory::TaskId>,
27 },
28
29 AllocationTracking {
31 event_type: AllocationEventType,
32 message: Arc<str>,
33 allocation_size: Option<usize>,
34 },
35
36 BufferManagement {
38 buffer_type: BufferType,
39 message: Arc<str>,
40 events_lost: Option<usize>,
41 },
42
43 DataAggregation {
45 aggregator: Arc<str>,
46 message: Arc<str>,
47 partial_data_available: bool,
48 },
49
50 Integration {
52 component: Arc<str>,
53 message: Arc<str>,
54 fallback_available: bool,
55 },
56
57 System {
59 operation: Arc<str>,
60 message: Arc<str>,
61 source_error: Option<Arc<str>>,
62 },
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum TaskOperation {
68 IdGeneration,
70 Propagation,
72 Registration,
74 Cleanup,
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80pub enum AllocationEventType {
81 Allocation,
83 Deallocation,
85 BufferWrite,
87 Processing,
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum BufferType {
94 AllocationEvents,
96 TaskProfiles,
98 QualityMetrics,
100}
101
102impl AsyncError {
103 pub fn initialization(component: &str, message: &str, recoverable: bool) -> Self {
105 Self::Initialization {
106 component: Arc::from(component),
107 message: Arc::from(message),
108 recoverable,
109 }
110 }
111
112 pub fn task_tracking(
114 operation: TaskOperation,
115 message: &str,
116 task_id: Option<crate::async_memory::TaskId>,
117 ) -> Self {
118 Self::TaskTracking {
119 operation,
120 message: Arc::from(message),
121 task_id,
122 }
123 }
124
125 pub fn allocation_tracking(
127 event_type: AllocationEventType,
128 message: &str,
129 allocation_size: Option<usize>,
130 ) -> Self {
131 Self::AllocationTracking {
132 event_type,
133 message: Arc::from(message),
134 allocation_size,
135 }
136 }
137
138 pub fn buffer_management(
140 buffer_type: BufferType,
141 message: &str,
142 events_lost: Option<usize>,
143 ) -> Self {
144 Self::BufferManagement {
145 buffer_type,
146 message: Arc::from(message),
147 events_lost,
148 }
149 }
150
151 pub fn data_aggregation(aggregator: &str, message: &str, partial_data: bool) -> Self {
153 Self::DataAggregation {
154 aggregator: Arc::from(aggregator),
155 message: Arc::from(message),
156 partial_data_available: partial_data,
157 }
158 }
159
160 pub fn integration(component: &str, message: &str, fallback_available: bool) -> Self {
162 Self::Integration {
163 component: Arc::from(component),
164 message: Arc::from(message),
165 fallback_available,
166 }
167 }
168
169 pub fn system(operation: &str, message: &str, source: Option<&str>) -> Self {
171 Self::System {
172 operation: Arc::from(operation),
173 message: Arc::from(message),
174 source_error: source.map(Arc::from),
175 }
176 }
177
178 pub fn is_recoverable(&self) -> bool {
180 match self {
181 Self::Initialization { recoverable, .. } => *recoverable,
182 Self::TaskTracking { .. } => true, Self::AllocationTracking { .. } => true, Self::BufferManagement { .. } => true, Self::DataAggregation {
186 partial_data_available,
187 ..
188 } => *partial_data_available,
189 Self::Integration {
190 fallback_available, ..
191 } => *fallback_available,
192 Self::System { .. } => false, }
194 }
195
196 pub fn component(&self) -> &str {
198 match self {
199 Self::Initialization { component, .. } => component,
200 Self::TaskTracking { .. } => "task_tracking",
201 Self::AllocationTracking { .. } => "allocation_tracking",
202 Self::BufferManagement { .. } => "buffer_management",
203 Self::DataAggregation { aggregator, .. } => aggregator,
204 Self::Integration { component, .. } => component,
205 Self::System { operation, .. } => operation,
206 }
207 }
208
209 pub fn message(&self) -> &str {
211 match self {
212 Self::Initialization { message, .. }
213 | Self::TaskTracking { message, .. }
214 | Self::AllocationTracking { message, .. }
215 | Self::BufferManagement { message, .. }
216 | Self::DataAggregation { message, .. }
217 | Self::Integration { message, .. }
218 | Self::System { message, .. } => message,
219 }
220 }
221}
222
223impl fmt::Display for AsyncError {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 match self {
226 Self::Initialization {
227 component,
228 message,
229 recoverable,
230 } => {
231 write!(
232 f,
233 "Async memory tracking initialization failed in {}: {} ({})",
234 component,
235 message,
236 if *recoverable { "recoverable" } else { "fatal" }
237 )
238 }
239 Self::TaskTracking {
240 operation,
241 message,
242 task_id,
243 } => {
244 if let Some(id) = task_id {
245 write!(
246 f,
247 "Task tracking error during {:?} for task {}: {}",
248 operation, id, message
249 )
250 } else {
251 write!(f, "Task tracking error during {:?}: {}", operation, message)
252 }
253 }
254 Self::AllocationTracking {
255 event_type,
256 message,
257 allocation_size,
258 } => {
259 if let Some(size) = allocation_size {
260 write!(
261 f,
262 "Allocation tracking error during {:?} ({}B): {}",
263 event_type, size, message
264 )
265 } else {
266 write!(
267 f,
268 "Allocation tracking error during {:?}: {}",
269 event_type, message
270 )
271 }
272 }
273 Self::BufferManagement {
274 buffer_type,
275 message,
276 events_lost,
277 } => {
278 if let Some(lost) = events_lost {
279 write!(
280 f,
281 "Buffer management error in {:?} ({} events lost): {}",
282 buffer_type, lost, message
283 )
284 } else {
285 write!(
286 f,
287 "Buffer management error in {:?}: {}",
288 buffer_type, message
289 )
290 }
291 }
292 Self::DataAggregation {
293 aggregator,
294 message,
295 partial_data_available,
296 } => {
297 write!(
298 f,
299 "Data aggregation error in {}: {} (partial data: {})",
300 aggregator, message, partial_data_available
301 )
302 }
303 Self::Integration {
304 component,
305 message,
306 fallback_available,
307 } => {
308 write!(
309 f,
310 "Integration error with {}: {} (fallback: {})",
311 component,
312 message,
313 if *fallback_available {
314 "available"
315 } else {
316 "unavailable"
317 }
318 )
319 }
320 Self::System {
321 operation,
322 message,
323 source_error,
324 } => {
325 if let Some(source) = source_error {
326 write!(
327 f,
328 "System error during {}: {} (source: {})",
329 operation, message, source
330 )
331 } else {
332 write!(f, "System error during {}: {}", operation, message)
333 }
334 }
335 }
336 }
337}
338
339impl std::error::Error for AsyncError {
340 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
341 None
343 }
344}
345
346pub type AsyncResult<T> = Result<T, AsyncError>;
348
349#[cfg(test)]
350mod tests {
351 use super::*;
352 use std::error::Error;
353
354 #[test]
355 fn test_error_creation() {
356 let error = AsyncError::initialization("tracker", "Failed to start", true);
357 assert!(error.is_recoverable());
358 assert_eq!(error.component(), "tracker");
359 assert_eq!(error.message(), "Failed to start");
360 }
361
362 #[test]
363 fn test_error_display() {
364 let error =
365 AsyncError::task_tracking(TaskOperation::IdGeneration, "Invalid context", Some(12345));
366 let display = format!("{}", error);
367 assert!(display.contains("IdGeneration"));
368 assert!(display.contains("12345"));
369 assert!(display.contains("Invalid context"));
370 }
371
372 #[test]
373 fn test_buffer_error_with_events_lost() {
374 let error = AsyncError::buffer_management(
375 BufferType::AllocationEvents,
376 "Buffer overflow",
377 Some(42),
378 );
379 let display = format!("{}", error);
380 assert!(display.contains("42 events lost"));
381 }
382
383 #[test]
384 fn test_error_recoverability() {
385 assert!(
387 AsyncError::task_tracking(TaskOperation::Propagation, "test", None).is_recoverable()
388 );
389 assert!(
390 AsyncError::allocation_tracking(AllocationEventType::Allocation, "test", None)
391 .is_recoverable()
392 );
393
394 assert!(!AsyncError::system("io", "disk failure", None).is_recoverable());
396 }
397
398 #[test]
399 fn test_initialization_error_non_recoverable() {
400 let error = AsyncError::initialization("runtime", "Critical failure", false);
401 assert!(!error.is_recoverable());
402 assert_eq!(error.component(), "runtime");
403 assert_eq!(error.message(), "Critical failure");
404
405 let display = format!("{}", error);
406 assert!(display.contains("fatal"));
407 assert!(display.contains("runtime"));
408 assert!(display.contains("Critical failure"));
409 }
410
411 #[test]
412 fn test_task_tracking_all_operations() {
413 let operations = [
414 TaskOperation::IdGeneration,
415 TaskOperation::Propagation,
416 TaskOperation::Registration,
417 TaskOperation::Cleanup,
418 ];
419
420 for op in &operations {
421 let error = AsyncError::task_tracking(*op, "test message", None);
422 assert!(error.is_recoverable());
423 assert_eq!(error.component(), "task_tracking");
424
425 let display = format!("{}", error);
426 assert!(display.contains(&format!("{:?}", op)));
427 }
428 }
429
430 #[test]
431 fn test_task_tracking_without_task_id() {
432 let error = AsyncError::task_tracking(TaskOperation::Registration, "No task ID", None);
433 let display = format!("{}", error);
434 assert!(display.contains("Registration"));
435 assert!(display.contains("No task ID"));
436 assert!(!display.contains("for task"));
438 }
439
440 #[test]
441 fn test_allocation_tracking_all_event_types() {
442 let event_types = [
443 AllocationEventType::Allocation,
444 AllocationEventType::Deallocation,
445 AllocationEventType::BufferWrite,
446 AllocationEventType::Processing,
447 ];
448
449 for event_type in &event_types {
450 let error = AsyncError::allocation_tracking(*event_type, "test", Some(1024));
451 assert!(error.is_recoverable());
452 assert_eq!(error.component(), "allocation_tracking");
453
454 let display = format!("{}", error);
455 assert!(display.contains(&format!("{:?}", event_type)));
456 assert!(display.contains("1024B"));
457 }
458 }
459
460 #[test]
461 fn test_allocation_tracking_without_size() {
462 let error =
463 AsyncError::allocation_tracking(AllocationEventType::Processing, "Unknown size", None);
464 let display = format!("{}", error);
465 assert!(display.contains("Processing"));
466 assert!(display.contains("Unknown size"));
467 assert!(!display.contains("B):"));
468 }
469
470 #[test]
471 fn test_buffer_management_all_types() {
472 let buffer_types = [
473 BufferType::AllocationEvents,
474 BufferType::TaskProfiles,
475 BufferType::QualityMetrics,
476 ];
477
478 for buffer_type in &buffer_types {
479 let error = AsyncError::buffer_management(*buffer_type, "test error", None);
480 assert!(error.is_recoverable());
481 assert_eq!(error.component(), "buffer_management");
482
483 let display = format!("{}", error);
484 assert!(display.contains(&format!("{:?}", buffer_type)));
485 }
486 }
487
488 #[test]
489 fn test_buffer_management_without_events_lost() {
490 let error =
491 AsyncError::buffer_management(BufferType::TaskProfiles, "Generic buffer error", None);
492 let display = format!("{}", error);
493 assert!(display.contains("TaskProfiles"));
494 assert!(display.contains("Generic buffer error"));
495 assert!(!display.contains("events lost"));
496 }
497
498 #[test]
499 fn test_data_aggregation_with_partial_data() {
500 let error = AsyncError::data_aggregation("metrics_collector", "Incomplete data", true);
501 assert!(error.is_recoverable());
502 assert_eq!(error.component(), "metrics_collector");
503 assert_eq!(error.message(), "Incomplete data");
504
505 let display = format!("{}", error);
506 assert!(display.contains("metrics_collector"));
507 assert!(display.contains("partial data: true"));
508 }
509
510 #[test]
511 fn test_data_aggregation_without_partial_data() {
512 let error = AsyncError::data_aggregation("failed_aggregator", "Total failure", false);
513 assert!(!error.is_recoverable());
514 assert_eq!(error.component(), "failed_aggregator");
515
516 let display = format!("{}", error);
517 assert!(display.contains("partial data: false"));
518 }
519
520 #[test]
521 fn test_integration_with_fallback() {
522 let error = AsyncError::integration("tokio", "Runtime unavailable", true);
523 assert!(error.is_recoverable());
524 assert_eq!(error.component(), "tokio");
525
526 let display = format!("{}", error);
527 assert!(display.contains("tokio"));
528 assert!(display.contains("fallback: available"));
529 }
530
531 #[test]
532 fn test_integration_without_fallback() {
533 let error = AsyncError::integration("tracing", "Critical dependency missing", false);
534 assert!(!error.is_recoverable());
535 assert_eq!(error.component(), "tracing");
536
537 let display = format!("{}", error);
538 assert!(display.contains("fallback: unavailable"));
539 }
540
541 #[test]
542 fn test_system_error_with_source() {
543 let error = AsyncError::system("file_io", "Write failed", Some("Permission denied"));
544 assert!(!error.is_recoverable());
545 assert_eq!(error.component(), "file_io");
546 assert_eq!(error.message(), "Write failed");
547
548 let display = format!("{}", error);
549 assert!(display.contains("file_io"));
550 assert!(display.contains("Write failed"));
551 assert!(display.contains("source: Permission denied"));
552 }
553
554 #[test]
555 fn test_system_error_without_source() {
556 let error = AsyncError::system("network", "Connection timeout", None);
557 assert!(!error.is_recoverable());
558
559 let display = format!("{}", error);
560 assert!(display.contains("network"));
561 assert!(display.contains("Connection timeout"));
562 assert!(!display.contains("source:"));
563 }
564
565 #[test]
566 fn test_enum_equality() {
567 assert_eq!(TaskOperation::IdGeneration, TaskOperation::IdGeneration);
569 assert_ne!(TaskOperation::IdGeneration, TaskOperation::Propagation);
570
571 assert_eq!(
573 AllocationEventType::Allocation,
574 AllocationEventType::Allocation
575 );
576 assert_ne!(
577 AllocationEventType::Allocation,
578 AllocationEventType::Deallocation
579 );
580
581 assert_eq!(BufferType::AllocationEvents, BufferType::AllocationEvents);
583 assert_ne!(BufferType::AllocationEvents, BufferType::TaskProfiles);
584 }
585
586 #[test]
587 fn test_enum_debug_formatting() {
588 let op = TaskOperation::Registration;
590 assert_eq!(format!("{:?}", op), "Registration");
591
592 let event = AllocationEventType::BufferWrite;
594 assert_eq!(format!("{:?}", event), "BufferWrite");
595
596 let buffer = BufferType::QualityMetrics;
598 assert_eq!(format!("{:?}", buffer), "QualityMetrics");
599 }
600
601 #[test]
602 fn test_error_clone() {
603 let original = AsyncError::initialization("test", "clone test", true);
604 let cloned = original.clone();
605
606 assert_eq!(original.component(), cloned.component());
607 assert_eq!(original.message(), cloned.message());
608 assert_eq!(original.is_recoverable(), cloned.is_recoverable());
609 }
610
611 #[test]
612 fn test_error_debug_formatting() {
613 let error = AsyncError::task_tracking(TaskOperation::Cleanup, "debug test", Some(999));
614 let debug_str = format!("{:?}", error);
615
616 assert!(debug_str.contains("TaskTracking"));
617 assert!(debug_str.contains("Cleanup"));
618 assert!(debug_str.contains("debug test"));
619 assert!(debug_str.contains("999"));
620 }
621
622 #[test]
623 fn test_error_source_method() {
624 let error = AsyncError::system("test", "source test", None);
625 assert!(error.source().is_none());
626 }
627
628 #[test]
629 fn test_async_result_type_alias() {
630 let success: AsyncResult<i32> = Ok(42);
631 assert!(success.is_ok());
632 if let Ok(value) = success {
633 assert_eq!(value, 42);
634 }
635
636 let failure: AsyncResult<i32> = Err(AsyncError::system("test", "fail", None));
637 assert!(failure.is_err());
638 }
639
640 #[test]
641 fn test_comprehensive_error_scenarios() {
642 let large_id_error = AsyncError::task_tracking(
646 TaskOperation::IdGeneration,
647 "Large ID test",
648 Some(u128::MAX),
649 );
650 let display = format!("{}", large_id_error);
651 assert!(display.contains(&u128::MAX.to_string()));
652
653 let zero_size_error = AsyncError::allocation_tracking(
655 AllocationEventType::Allocation,
656 "Zero size allocation",
657 Some(0),
658 );
659 let display = format!("{}", zero_size_error);
660 assert!(display.contains("0B"));
661
662 let large_lost_error = AsyncError::buffer_management(
664 BufferType::AllocationEvents,
665 "Massive overflow",
666 Some(1_000_000),
667 );
668 let display = format!("{}", large_lost_error);
669 assert!(display.contains("1000000 events lost"));
670 }
671}