Skip to content

Commit c13016a

Browse files
senekorjannau
authored andcommitted
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>
1 parent 9d199a7 commit c13016a

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

rust/kernel/device/property.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,65 @@ unsafe impl crate::types::AlwaysRefCounted for FwNode {
105105
}
106106
}
107107

108+
/// A helper for reading device properties.
109+
///
110+
/// Use [`Self::required_by`] if a missing property is considered a bug and
111+
/// [`Self::optional`] otherwise.
112+
///
113+
/// For convenience, [`Self::or`] and [`Self::or_default`] are provided.
114+
pub struct PropertyGuard<'fwnode, 'name, T> {
115+
/// The result of reading the property.
116+
inner: Result<T>,
117+
/// The fwnode of the property, used for logging in the "required" case.
118+
fwnode: &'fwnode FwNode,
119+
/// The name of the property, used for logging in the "required" case.
120+
name: &'name CStr,
121+
}
122+
123+
impl<T> PropertyGuard<'_, '_, T> {
124+
/// Access the property, indicating it is required.
125+
///
126+
/// If the property is not present, the error is automatically logged. If a
127+
/// missing property is not an error, use [`Self::optional`] instead. The
128+
/// device is required to associate the log with it.
129+
pub fn required_by(self, dev: &super::Device) -> Result<T> {
130+
if self.inner.is_err() {
131+
dev_err!(
132+
dev,
133+
"{}: property '{}' is missing\n",
134+
self.fwnode,
135+
self.name
136+
);
137+
}
138+
self.inner
139+
}
140+
141+
/// Access the property, indicating it is optional.
142+
///
143+
/// In contrast to [`Self::required_by`], no error message is logged if
144+
/// the property is not present.
145+
pub fn optional(self) -> Option<T> {
146+
self.inner.ok()
147+
}
148+
149+
/// Access the property or the specified default value.
150+
///
151+
/// Do not pass a sentinel value as default to detect a missing property.
152+
/// Use [`Self::required_by`] or [`Self::optional`] instead.
153+
pub fn or(self, default: T) -> T {
154+
self.inner.unwrap_or(default)
155+
}
156+
}
157+
158+
impl<T: Default> PropertyGuard<'_, '_, T> {
159+
/// Access the property or a default value.
160+
///
161+
/// Use [`Self::or`] to specify a custom default value.
162+
pub fn or_default(self) -> T {
163+
self.inner.unwrap_or_default()
164+
}
165+
}
166+
108167
enum Node<'a> {
109168
Borrowed(&'a FwNode),
110169
Owned(ARef<FwNode>),

0 commit comments

Comments
 (0)