Error Handling
Relevant source files
The following files were used as context for generating this wiki page:
The battery crate implements a centralized error handling strategy designed to wrap diverse platform-specific I/O errors into a unified interface. Since the library interacts directly with operating system interfaces (such as Linux sysfs, macOS IOKit, or NetBSD envsys), the primary source of failure is I/O-related. The error handling system provides a thin wrapper around std::io::Error while allowing for custom context via descriptive strings.
Sources: src/errors.rs:1-15, src/lib.rs:37-41
Core Error Structure
The central component of the error system is the Error struct. It encapsulates an underlying std::io::Error and an optional Cow<'static, str> description. This design allows the library to maintain the original OS error code while providing developer-friendly context about which specific battery routine failed.
Data Structures
| Component | Type | Description |
|---|---|---|
Error | struct | Main error container holding source and description. |
Result<T> | type alias | Shortcut for std::result::Result<T, Error>. |
description | Option<Cow<'static, str>> | Custom message for debugging purposes. |
source | std::io::Error | The underlying standard I/O error. |
Sources: src/errors.rs:13-21
Error Architecture
The following diagram illustrates how the Error struct wraps standard and platform-specific errors into a unified type used across the crate.
The Error struct implements std::fmt::Display. If a custom description is present, it is used for the display output; otherwise, it falls back to the underlying io::Error formatting.
Sources: src/errors.rs:60-67
Platform-Specific Conversions
The library provides specialized conversions for different operating systems to ensure native errors are mapped correctly to the internal Error type.
Unix and BSD Systems
For platforms like FreeBSD, DragonFlyBSD, and NetBSD, the crate implements a conversion from nix::Error. This conversion preserves the raw OS error code using io::Error::from_raw_os_error.
Sources: src/errors.rs:77-90
NetBSD Plist Handling
On NetBSD, battery data is often processed via property lists. The system includes a specific implementation for plist::Error. If a plist::Error can be converted into an I/O error, it is wrapped as such; otherwise, it defaults to an InvalidData error kind.
Sources: src/errors.rs:93-105
Common Error Patterns
The crate utilizes several factory methods to create common error types encountered during battery data retrieval.
| Method | Error Kind | Use Case |
|---|---|---|
Error::not_found | io::ErrorKind::NotFound | Missing sysfs files or absent battery devices. |
Error::invalid_data | io::ErrorKind::InvalidData | Failure to parse file content or invalid units. |
Error::new | Variable | Custom wrapping of existing io::Error with context. |
Sources: src/errors.rs:32-52
Fallback and Recovery Logic
The library often handles specific OS errors by falling back to default values rather than terminating, particularly when dealing with non-critical missing files in Linux sysfs.
For example, in src/platform/linux/sysfs/fs.rs, the code explicitly handles ENODEV (Error 19) identically to NotFound. This prevents specific driver quirks from causing hard failures when optional battery attributes (like energy_full_design) are missing.
Sources: src/platform/linux/sysfs/fs.rs:97-111, src/platform/linux/sysfs/source.rs:139-152
Implementation Example: Linux Refresh
In the Linux implementation, the refresh method verifies the existence of the device directory. If the directory is missing, it constructs a descriptive NotFound error.
pub fn refresh(&mut self) -> Result<()> {
if self.root.is_dir() {
let builder = DataBuilder::new(&self.root);
self.source = builder.collect()?;
Ok(())
} else {
let inner = io::Error::from(io::ErrorKind::NotFound);
let e = Error::new(
inner,
format!("Device directory `{:?}` is missing", self.root),
);
Err(e)
}
}
Sources: src/platform/linux/device.rs:51-66
Summary
Error handling in rust-battery is designed to be transparent yet informative. By wrapping std::io::Error and providing specialized trait implementations for platform-specific crates (like nix and plist), the library ensures that callers receive a consistent battery::Error regardless of the underlying operating system while retaining the ability to inspect the root cause of I/O failures.