1
0

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:
Remo Senekowitsch
2025-06-11 12:29:04 +02:00
committed by Danilo Krummrich
parent ecea245981
commit 9bd791d941

View File

@@ -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()
}
}