embedded_charts/error.rs
1//! Error types and result handling for the embedded graphics chart library.
2//!
3//! This module provides comprehensive error handling for all chart operations while maintaining
4//! compatibility with both `std` and `no_std` environments. All error types implement the
5//! necessary traits for proper error propagation and debugging.
6//!
7//! # Error Categories
8//!
9//! The library uses a hierarchical error system with specific error types for different
10//! operation categories:
11//!
12//! - [`ChartError`] - Main error type for high-level chart operations
13//! - [`DataError`] - Errors related to data management and processing
14//! - [`RenderError`] - Errors during rendering and drawing operations
15//! - [`LayoutError`] - Errors in chart layout and positioning
16//! - [`AnimationError`] - Errors in animation system (feature-gated)
17//!
18//! # Error Handling Patterns
19//!
20//! ## Basic Error Handling
21//! ```rust
22//! use embedded_charts::prelude::*;
23//! use embedded_graphics::pixelcolor::Rgb565;
24//!
25//! let mut data: StaticDataSeries<Point2D, 256> = StaticDataSeries::new();
26//! match data.push(Point2D::new(0.0, 10.0)) {
27//! Ok(()) => println!("Data added successfully"),
28//! Err(DataError::BufferFull { .. }) => println!("Data series is full"),
29//! Err(e) => println!("Other error: {}", e),
30//! }
31//! ```
32//!
33//! ## Using Result Types
34//! ```rust
35//! # #[cfg(feature = "line")]
36//! # {
37//! use embedded_charts::prelude::*;
38//! use embedded_charts::error::ChartResult;
39//!
40//! fn create_chart() -> ChartResult<LineChart<embedded_graphics::pixelcolor::Rgb565>> {
41//! LineChart::builder()
42//! .line_color(embedded_graphics::pixelcolor::Rgb565::BLUE)
43//! .build()
44//! }
45//! # }
46//! ```
47//!
48//! ## Error Propagation
49//! ```rust
50//! use embedded_charts::prelude::*;
51//! use embedded_charts::error::{ChartResult, DataError};
52//!
53//! fn process_data() -> ChartResult<()> {
54//! let mut data: StaticDataSeries<Point2D, 256> = StaticDataSeries::new();
55//! data.push(Point2D::new(0.0, 10.0))?; // Automatically converts DataError to ChartError
56//! Ok(())
57//! }
58//! ```
59//!
60//! # no_std Compatibility
61//!
62//! All error types are designed to work in `no_std` environments:
63//! - No heap allocation for error messages
64//! - Implement `core::fmt::Display` instead of `std::fmt::Display`
65//! - Optional `std::error::Error` implementation when `std` feature is enabled
66//!
67//! # Memory Efficiency
68//!
69//! Error types are designed for minimal memory usage:
70//! - All error variants are `Copy` types
71//! - No dynamic string allocation
72//! - Efficient error code representation
73
74#[cfg(feature = "std")]
75extern crate std;
76
77/// Error context information for better debugging
78///
79/// This struct provides additional context for errors while maintaining
80/// no_std compatibility by using static string references.
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub struct ErrorContext {
83 /// The operation that was being performed when the error occurred
84 pub operation: &'static str,
85 /// A hint for resolving the error
86 pub hint: &'static str,
87 /// Optional numeric context (e.g., data point count, buffer size)
88 pub numeric_context: Option<usize>,
89}
90
91impl ErrorContext {
92 /// Create a new error context
93 pub const fn new(operation: &'static str, hint: &'static str) -> Self {
94 Self {
95 operation,
96 hint,
97 numeric_context: None,
98 }
99 }
100
101 /// Create error context with numeric information
102 pub const fn with_numeric(operation: &'static str, hint: &'static str, value: usize) -> Self {
103 Self {
104 operation,
105 hint,
106 numeric_context: Some(value),
107 }
108 }
109}
110
111/// Main error type for chart operations.
112///
113/// This is the primary error type returned by most chart operations. It encompasses
114/// all possible error conditions that can occur during chart creation, configuration,
115/// and rendering.
116///
117/// # Error Variants
118///
119/// - **Data-related errors**: Issues with data series, points, or bounds
120/// - **Rendering errors**: Problems during drawing operations
121/// - **Configuration errors**: Invalid chart or component configuration
122/// - **Memory errors**: Buffer overflow or allocation failures
123/// - **Animation errors**: Issues with animation system (feature-gated)
124///
125/// # Examples
126///
127/// ```rust,no_run
128/// use embedded_charts::prelude::*;
129/// use embedded_charts::error::ChartError;
130///
131/// // Example function that might return a ChartError
132/// fn render_chart() -> Result<(), ChartError> {
133/// // This would be actual chart rendering logic
134/// Err(ChartError::InsufficientData)
135/// }
136///
137/// match render_chart() {
138/// Ok(()) => println!("Chart rendered successfully"),
139/// Err(ChartError::InsufficientData) => println!("Not enough data to render"),
140/// Err(ChartError::MemoryFull) => println!("Out of memory"),
141/// Err(e) => println!("Other error: {}", e),
142/// }
143/// ```
144#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145pub enum ChartError {
146 /// Insufficient data to render the chart.
147 ///
148 /// This error occurs when a chart requires a minimum number of data points
149 /// but the provided data series doesn't meet that requirement.
150 InsufficientData,
151 /// Invalid range specified for axis or data.
152 ///
153 /// Returned when axis ranges are invalid (e.g., min > max) or when
154 /// data values fall outside expected ranges.
155 InvalidRange,
156 /// Invalid data provided.
157 ///
158 /// Generic error for data that doesn't meet the chart's requirements,
159 /// such as NaN values, infinite values, or malformed data points.
160 InvalidData,
161 /// Memory allocation failed or buffer is full.
162 ///
163 /// Occurs when static buffers reach capacity or when memory allocation
164 /// fails in `std` environments.
165 MemoryFull,
166 /// Error occurred during rendering.
167 ///
168 /// Generic rendering error for issues during the drawing process.
169 RenderingError,
170 /// Invalid configuration provided.
171 ///
172 /// Returned when chart configuration contains invalid or conflicting settings.
173 InvalidConfiguration,
174 /// Configuration error occurred.
175 ///
176 /// More specific configuration error, typically with additional context.
177 ConfigurationError,
178 /// Render error occurred.
179 ///
180 /// Specific rendering error with detailed error information.
181 RenderError(RenderError),
182 /// Layout error occurred.
183 ///
184 /// Error during chart layout calculation or component positioning.
185 LayoutError(LayoutError),
186 /// Data error occurred.
187 ///
188 /// Specific data-related error with detailed error information.
189 DataError(DataError),
190 /// Animation error occurred.
191 ///
192 /// Error in the animation system (only available with "animations" feature).
193 #[cfg(feature = "animations")]
194 AnimationError(AnimationError),
195}
196
197/// Error type for data operations.
198///
199/// This error type covers all data-related operations including data series
200/// management, data point validation, and data processing operations.
201///
202/// # Common Scenarios
203///
204/// - Adding data to a full buffer
205/// - Accessing data with invalid indices
206/// - Processing invalid data points
207/// - Data scaling and transformation errors
208///
209/// # Examples
210///
211/// ```rust
212/// use embedded_charts::prelude::*;
213/// use embedded_charts::error::DataError;
214///
215/// let mut series = StaticDataSeries::<Point2D, 10>::new();
216///
217/// // Fill the series to capacity
218/// for i in 0..10 {
219/// series.push(Point2D::new(i as f32, i as f32)).unwrap();
220/// }
221///
222/// // This will return BufferFull error with context
223/// match series.push(Point2D::new(10.0, 10.0)) {
224/// Err(DataError::BufferFull { context: Some(ctx) }) => {
225/// println!("Series is full: {}", ctx.hint);
226/// },
227/// _ => unreachable!(),
228/// }
229/// ```
230#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231pub enum DataError {
232 /// Requested data series was not found.
233 ///
234 /// Occurs when trying to access a data series by name or index
235 /// that doesn't exist in the collection.
236 SeriesNotFound {
237 /// Optional context information
238 context: Option<ErrorContext>,
239 },
240 /// Index is out of bounds for the data collection.
241 ///
242 /// Returned when accessing data with an invalid index.
243 IndexOutOfBounds {
244 /// Optional context information
245 context: Option<ErrorContext>,
246 },
247 /// Invalid data point provided.
248 ///
249 /// Occurs when a data point contains invalid values such as
250 /// NaN, infinity, or values outside acceptable ranges.
251 InvalidDataPoint {
252 /// Optional context information
253 context: Option<ErrorContext>,
254 },
255 /// Error occurred during data scaling.
256 ///
257 /// Returned when data scaling or normalization operations fail,
258 /// typically due to invalid ranges or mathematical errors.
259 ScalingError {
260 /// Optional context information
261 context: Option<ErrorContext>,
262 },
263 /// Buffer capacity exceeded.
264 ///
265 /// Occurs when trying to add data to a full static buffer.
266 BufferFull {
267 /// Optional context information
268 context: Option<ErrorContext>,
269 },
270 /// Insufficient data to perform operation.
271 ///
272 /// Returned when an operation requires a minimum amount of data
273 /// that isn't available.
274 InsufficientData {
275 /// Optional context information
276 context: Option<ErrorContext>,
277 },
278}
279
280impl DataError {
281 /// Create a BufferFull error with context
282 pub const fn buffer_full(operation: &'static str, capacity: usize) -> Self {
283 Self::BufferFull {
284 context: Some(ErrorContext::with_numeric(
285 operation,
286 "Increase buffer capacity or remove old data",
287 capacity,
288 )),
289 }
290 }
291
292 /// Create an InsufficientData error with context
293 pub const fn insufficient_data(
294 operation: &'static str,
295 _required: usize,
296 found: usize,
297 ) -> Self {
298 Self::InsufficientData {
299 context: Some(ErrorContext::with_numeric(
300 operation,
301 "Add more data points",
302 found,
303 )),
304 }
305 }
306
307 /// Create an IndexOutOfBounds error with context
308 pub const fn index_out_of_bounds(
309 operation: &'static str,
310 _index: usize,
311 length: usize,
312 ) -> Self {
313 Self::IndexOutOfBounds {
314 context: Some(ErrorContext::with_numeric(
315 operation,
316 "Check array bounds before accessing",
317 length,
318 )),
319 }
320 }
321
322 /// Create an InvalidDataPoint error with context
323 pub const fn invalid_data_point(operation: &'static str) -> Self {
324 Self::InvalidDataPoint {
325 context: Some(ErrorContext::new(
326 operation,
327 "Ensure data points contain valid finite values",
328 )),
329 }
330 }
331
332 /// Create a simple error without context (for backwards compatibility)
333 pub const fn simple(kind: DataErrorKind) -> Self {
334 match kind {
335 DataErrorKind::SeriesNotFound => Self::SeriesNotFound { context: None },
336 DataErrorKind::IndexOutOfBounds => Self::IndexOutOfBounds { context: None },
337 DataErrorKind::InvalidDataPoint => Self::InvalidDataPoint { context: None },
338 DataErrorKind::ScalingError => Self::ScalingError { context: None },
339 DataErrorKind::BufferFull => Self::BufferFull { context: None },
340 DataErrorKind::InsufficientData => Self::InsufficientData { context: None },
341 }
342 }
343}
344
345// Backwards compatibility constants
346impl DataError {
347 /// Backwards compatibility: SeriesNotFound variant without context
348 pub const SERIES_NOT_FOUND: Self = Self::SeriesNotFound { context: None };
349
350 /// Backwards compatibility: IndexOutOfBounds variant without context
351 pub const INDEX_OUT_OF_BOUNDS: Self = Self::IndexOutOfBounds { context: None };
352
353 /// Backwards compatibility: InvalidDataPoint variant without context
354 pub const INVALID_DATA_POINT: Self = Self::InvalidDataPoint { context: None };
355
356 /// Backwards compatibility: ScalingError variant without context
357 pub const SCALING_ERROR: Self = Self::ScalingError { context: None };
358
359 /// Backwards compatibility: BufferFull variant without context
360 pub const BUFFER_FULL: Self = Self::BufferFull { context: None };
361
362 /// Backwards compatibility: InsufficientData variant without context
363 pub const INSUFFICIENT_DATA: Self = Self::InsufficientData { context: None };
364}
365
366/// Data error kinds for backwards compatibility
367#[derive(Debug, Clone, Copy, PartialEq, Eq)]
368pub enum DataErrorKind {
369 /// Requested data series was not found
370 SeriesNotFound,
371 /// Index is out of bounds for the data collection
372 IndexOutOfBounds,
373 /// Invalid data point provided
374 InvalidDataPoint,
375 /// Error occurred during data scaling
376 ScalingError,
377 /// Buffer capacity exceeded
378 BufferFull,
379 /// Insufficient data to perform operation
380 InsufficientData,
381}
382
383/// Error type for animation operations.
384///
385/// This error type is only available when the "animations" feature is enabled.
386/// It covers all animation-related operations including animation scheduling,
387/// interpolation, and state management.
388///
389/// # Common Scenarios
390///
391/// - Invalid animation duration
392/// - Animation scheduler at capacity
393/// - Interpolation failures
394/// - Invalid animation state transitions
395///
396/// # Examples
397///
398/// ```rust,no_run
399/// # #[cfg(feature = "animations")]
400/// # {
401/// use embedded_charts::prelude::*;
402/// use embedded_charts::error::AnimationError;
403///
404/// // Example function that might return an AnimationError
405/// fn start_animation() -> Result<u32, AnimationError> {
406/// // This would be actual animation logic
407/// Err(AnimationError::InvalidDuration)
408/// }
409///
410/// match start_animation() {
411/// Ok(animation_id) => println!("Animation started: {}", animation_id),
412/// Err(AnimationError::InvalidDuration) => println!("Duration must be positive"),
413/// Err(AnimationError::SchedulerFull) => println!("Too many active animations"),
414/// Err(e) => println!("Animation error: {}", e),
415/// }
416/// # }
417/// ```
418#[cfg(feature = "animations")]
419#[derive(Debug, Clone, Copy, PartialEq, Eq)]
420pub enum AnimationError {
421 /// Invalid duration specified.
422 ///
423 /// Occurs when animation duration is zero, negative, or exceeds
424 /// maximum allowed duration.
425 InvalidDuration,
426 /// Animation with specified ID was not found.
427 ///
428 /// Returned when trying to access or modify an animation that
429 /// doesn't exist or has already completed.
430 AnimationNotFound,
431 /// Animation scheduler is full.
432 ///
433 /// Occurs when trying to start a new animation but the scheduler
434 /// has reached its maximum capacity.
435 SchedulerFull,
436 /// Error occurred during interpolation.
437 ///
438 /// Returned when interpolation between animation keyframes fails,
439 /// typically due to incompatible data types or invalid values.
440 InterpolationError,
441 /// Animation state is invalid.
442 ///
443 /// Occurs when an animation operation is attempted on an animation
444 /// in an inappropriate state (e.g., trying to pause a completed animation).
445 InvalidState,
446}
447
448/// Error type for layout operations.
449///
450/// This error type covers chart layout calculations, component positioning,
451/// and space allocation operations.
452///
453/// # Common Scenarios
454///
455/// - Insufficient space for chart components
456/// - Invalid layout configuration
457/// - Component positioning failures
458///
459/// # Examples
460///
461/// ```rust,no_run
462/// use embedded_charts::prelude::*;
463/// use embedded_charts::error::LayoutError;
464/// use embedded_graphics::prelude::*;
465///
466/// // Example function that might return a LayoutError
467/// fn check_layout_error() -> Result<(), LayoutError> {
468/// // This would be actual layout calculation logic
469/// Err(LayoutError::InsufficientSpace)
470/// }
471///
472/// match check_layout_error() {
473/// Ok(()) => println!("Layout calculated successfully"),
474/// Err(LayoutError::InsufficientSpace) => println!("Viewport too small"),
475/// Err(LayoutError::InvalidConfiguration) => println!("Invalid layout config"),
476/// Err(e) => println!("Layout error: {}", e),
477/// }
478/// ```
479#[derive(Debug, Clone, Copy, PartialEq, Eq)]
480pub enum LayoutError {
481 /// Insufficient space for layout.
482 ///
483 /// Occurs when the available viewport is too small to accommodate
484 /// the chart and its components with the current configuration.
485 InsufficientSpace,
486 /// Invalid layout configuration.
487 ///
488 /// Returned when layout parameters are invalid or conflicting,
489 /// such as negative margins or impossible component arrangements.
490 InvalidConfiguration,
491 /// Component positioning failed.
492 ///
493 /// Occurs when individual chart components cannot be positioned
494 /// within the available space, even with valid overall layout.
495 PositioningFailed,
496}
497
498/// Error type for rendering operations.
499///
500/// This error type covers low-level rendering operations including drawing
501/// primitives, text rendering, and color operations.
502///
503/// # Common Scenarios
504///
505/// - Drawing operation failures
506/// - Text rendering issues
507/// - Color conversion problems
508/// - Clipping operation failures
509///
510/// # Examples
511///
512/// ```rust,no_run
513/// use embedded_charts::prelude::*;
514/// use embedded_charts::error::RenderError;
515///
516/// // Example function that might return a RenderError
517/// fn draw_something() -> Result<(), RenderError> {
518/// // This would be actual rendering logic
519/// Err(RenderError::DrawingFailed)
520/// }
521///
522/// match draw_something() {
523/// Ok(()) => println!("Drawing completed successfully"),
524/// Err(RenderError::DrawingFailed) => println!("Failed to draw"),
525/// Err(RenderError::ColorConversionFailed) => println!("Invalid color"),
526/// Err(e) => println!("Render error: {}", e),
527/// }
528/// ```
529#[derive(Debug, Clone, Copy, PartialEq, Eq)]
530pub enum RenderError {
531 /// Drawing operation failed.
532 ///
533 /// Generic error for drawing operations that fail due to
534 /// display driver issues or invalid drawing parameters.
535 DrawingFailed,
536 /// Text rendering failed.
537 ///
538 /// Occurs when text cannot be rendered, typically due to
539 /// font issues, invalid characters, or display limitations.
540 TextRenderingFailed,
541 /// Clipping operation failed.
542 ///
543 /// Returned when clipping regions cannot be established
544 /// or when clipping operations fail.
545 ClippingFailed,
546 /// Color conversion failed.
547 ///
548 /// Occurs when color values cannot be converted between
549 /// different color spaces or pixel formats.
550 ColorConversionFailed,
551}
552
553impl From<&str> for DataError {
554 fn from(_msg: &str) -> Self {
555 // For no_std compatibility, we can't store the string message
556 // so we return a generic error variant
557 DataError::simple(DataErrorKind::InvalidDataPoint)
558 }
559}
560
561impl From<DataError> for ChartError {
562 fn from(error: DataError) -> Self {
563 ChartError::DataError(error)
564 }
565}
566
567#[cfg(feature = "animations")]
568impl From<AnimationError> for ChartError {
569 fn from(error: AnimationError) -> Self {
570 ChartError::AnimationError(error)
571 }
572}
573
574impl From<LayoutError> for ChartError {
575 fn from(_error: LayoutError) -> Self {
576 ChartError::InvalidConfiguration
577 }
578}
579
580impl From<RenderError> for ChartError {
581 fn from(_error: RenderError) -> Self {
582 ChartError::RenderingError
583 }
584}
585
586/// Result type for chart operations
587pub type ChartResult<T> = Result<T, ChartError>;
588
589/// Result type for data operations
590pub type DataResult<T> = Result<T, DataError>;
591
592/// Result type for animation operations
593#[cfg(feature = "animations")]
594pub type AnimationResult<T> = Result<T, AnimationError>;
595
596/// Result type for layout operations
597pub type LayoutResult<T> = Result<T, LayoutError>;
598
599/// Result type for rendering operations
600pub type RenderResult<T> = Result<T, RenderError>;
601
602// Implement std::error::Error trait for error types when std is available
603#[cfg(feature = "std")]
604impl std::error::Error for ChartError {
605 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
606 match self {
607 ChartError::DataError(err) => Some(err),
608 ChartError::RenderError(err) => Some(err),
609 ChartError::LayoutError(err) => Some(err),
610 #[cfg(feature = "animations")]
611 ChartError::AnimationError(err) => Some(err),
612 _ => None,
613 }
614 }
615}
616
617#[cfg(feature = "std")]
618impl std::error::Error for DataError {}
619
620#[cfg(feature = "animations")]
621#[cfg(feature = "std")]
622impl std::error::Error for AnimationError {}
623
624#[cfg(feature = "std")]
625impl std::error::Error for LayoutError {}
626
627#[cfg(feature = "std")]
628impl std::error::Error for RenderError {}
629
630// Implement Display trait for error types
631impl core::fmt::Display for ChartError {
632 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
633 match self {
634 ChartError::InsufficientData => write!(f, "Insufficient data to render the chart"),
635 ChartError::InvalidRange => write!(f, "Invalid range specified for axis or data"),
636 ChartError::InvalidData => write!(f, "Invalid data provided"),
637 ChartError::MemoryFull => write!(f, "Memory allocation failed or buffer is full"),
638 ChartError::RenderingError => write!(f, "Error occurred during rendering"),
639 ChartError::InvalidConfiguration => write!(f, "Invalid configuration provided"),
640 ChartError::ConfigurationError => write!(f, "Configuration error occurred"),
641 ChartError::RenderError(err) => write!(f, "Render error: {err}"),
642 ChartError::LayoutError(err) => write!(f, "Layout error: {err}"),
643 ChartError::DataError(err) => write!(f, "Data error: {err}"),
644 #[cfg(feature = "animations")]
645 ChartError::AnimationError(err) => write!(f, "Animation error: {err}"),
646 }
647 }
648}
649
650impl core::fmt::Display for DataError {
651 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
652 match self {
653 DataError::SeriesNotFound { context } => {
654 write!(f, "Requested data series was not found")?;
655 if let Some(ctx) = context {
656 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
657 }
658 Ok(())
659 }
660 DataError::IndexOutOfBounds { context } => {
661 write!(f, "Index is out of bounds for the data collection")?;
662 if let Some(ctx) = context {
663 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
664 if let Some(value) = ctx.numeric_context {
665 write!(f, " [length: {value}]")?;
666 }
667 }
668 Ok(())
669 }
670 DataError::InvalidDataPoint { context } => {
671 write!(f, "Invalid data point provided")?;
672 if let Some(ctx) = context {
673 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
674 }
675 Ok(())
676 }
677 DataError::ScalingError { context } => {
678 write!(f, "Error occurred during data scaling")?;
679 if let Some(ctx) = context {
680 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
681 }
682 Ok(())
683 }
684 DataError::BufferFull { context } => {
685 write!(f, "Buffer capacity exceeded")?;
686 if let Some(ctx) = context {
687 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
688 if let Some(capacity) = ctx.numeric_context {
689 write!(f, " [capacity: {capacity}]")?;
690 }
691 }
692 Ok(())
693 }
694 DataError::InsufficientData { context } => {
695 write!(f, "Insufficient data to perform operation")?;
696 if let Some(ctx) = context {
697 write!(f, " during {} (hint: {})", ctx.operation, ctx.hint)?;
698 if let Some(found) = ctx.numeric_context {
699 write!(f, " [found: {found}]")?;
700 }
701 }
702 Ok(())
703 }
704 }
705 }
706}
707
708#[cfg(feature = "animations")]
709impl core::fmt::Display for AnimationError {
710 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
711 match self {
712 AnimationError::InvalidDuration => write!(f, "Invalid duration specified"),
713 AnimationError::AnimationNotFound => {
714 write!(f, "Animation with specified ID was not found")
715 }
716 AnimationError::SchedulerFull => write!(f, "Animation scheduler is full"),
717 AnimationError::InterpolationError => write!(f, "Error occurred during interpolation"),
718 AnimationError::InvalidState => write!(f, "Animation state is invalid"),
719 }
720 }
721}
722
723impl core::fmt::Display for LayoutError {
724 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
725 match self {
726 LayoutError::InsufficientSpace => write!(f, "Insufficient space for layout"),
727 LayoutError::InvalidConfiguration => write!(f, "Invalid layout configuration"),
728 LayoutError::PositioningFailed => write!(f, "Component positioning failed"),
729 }
730 }
731}
732
733impl core::fmt::Display for RenderError {
734 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
735 match self {
736 RenderError::DrawingFailed => write!(f, "Drawing operation failed"),
737 RenderError::TextRenderingFailed => write!(f, "Text rendering failed"),
738 RenderError::ClippingFailed => write!(f, "Clipping operation failed"),
739 RenderError::ColorConversionFailed => write!(f, "Color conversion failed"),
740 }
741 }
742}