rust: device: Introduce PropertyGuard
This abstraction is a way to force users to specify whether a property is supposed to be required or not. This allows us to move error logging of missing required properties into core, preventing a lot of boilerplate in drivers. It will be used by upcoming methods for reading device properties. Tested-by: Dirk Behme <dirk.behme@de.bosch.com> Signed-off-by: Remo Senekowitsch <remo@buenzli.dev> Link: https://lore.kernel.org/r/20250611102908.212514-6-remo@buenzli.dev [ Use prelude::* to avoid build failure; move PropertyGuard below Display impl of FwNode. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
committed by
Danilo Krummrich
parent
ecea245981
commit
9bd791d941
@@ -8,6 +8,7 @@ use core::ptr;
|
||||
|
||||
use crate::{
|
||||
bindings,
|
||||
prelude::*,
|
||||
str::CStr,
|
||||
types::{ARef, Opaque},
|
||||
};
|
||||
@@ -154,3 +155,62 @@ impl core::fmt::Display for FwNode {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper for reading device properties.
|
||||
///
|
||||
/// Use [`Self::required_by`] if a missing property is considered a bug and
|
||||
/// [`Self::optional`] otherwise.
|
||||
///
|
||||
/// For convenience, [`Self::or`] and [`Self::or_default`] are provided.
|
||||
pub struct PropertyGuard<'fwnode, 'name, T> {
|
||||
/// The result of reading the property.
|
||||
inner: Result<T>,
|
||||
/// The fwnode of the property, used for logging in the "required" case.
|
||||
fwnode: &'fwnode FwNode,
|
||||
/// The name of the property, used for logging in the "required" case.
|
||||
name: &'name CStr,
|
||||
}
|
||||
|
||||
impl<T> PropertyGuard<'_, '_, T> {
|
||||
/// Access the property, indicating it is required.
|
||||
///
|
||||
/// If the property is not present, the error is automatically logged. If a
|
||||
/// missing property is not an error, use [`Self::optional`] instead. The
|
||||
/// device is required to associate the log with it.
|
||||
pub fn required_by(self, dev: &super::Device) -> Result<T> {
|
||||
if self.inner.is_err() {
|
||||
dev_err!(
|
||||
dev,
|
||||
"{}: property '{}' is missing\n",
|
||||
self.fwnode,
|
||||
self.name
|
||||
);
|
||||
}
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Access the property, indicating it is optional.
|
||||
///
|
||||
/// In contrast to [`Self::required_by`], no error message is logged if
|
||||
/// the property is not present.
|
||||
pub fn optional(self) -> Option<T> {
|
||||
self.inner.ok()
|
||||
}
|
||||
|
||||
/// Access the property or the specified default value.
|
||||
///
|
||||
/// Do not pass a sentinel value as default to detect a missing property.
|
||||
/// Use [`Self::required_by`] or [`Self::optional`] instead.
|
||||
pub fn or(self, default: T) -> T {
|
||||
self.inner.unwrap_or(default)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> PropertyGuard<'_, '_, T> {
|
||||
/// Access the property or a default value.
|
||||
///
|
||||
/// Use [`Self::or`] to specify a custom default value.
|
||||
pub fn or_default(self) -> T {
|
||||
self.inner.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user