xref: /linux/rust/kernel/device/property.rs (revision 644672e93a1aa6bfc3ebc102cbf9b8efad16e786)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Unified device property interface.
4 //!
5 //! C header: [`include/linux/property.h`](srctree/include/linux/property.h)
6 
7 use core::{mem::MaybeUninit, ptr};
8 
9 use super::private::Sealed;
10 use crate::{
11     alloc::KVec,
12     bindings,
13     error::{to_result, Result},
14     fmt,
15     prelude::*,
16     str::{CStr, CString},
17     sync::aref::ARef,
18     types::Opaque,
19 };
20 
21 /// A reference-counted fwnode_handle.
22 ///
23 /// This structure represents the Rust abstraction for a
24 /// C `struct fwnode_handle`. This implementation abstracts the usage of an
25 /// already existing C `struct fwnode_handle` within Rust code that we get
26 /// passed from the C side.
27 ///
28 /// # Invariants
29 ///
30 /// A `FwNode` instance represents a valid `struct fwnode_handle` created by the
31 /// C portion of the kernel.
32 ///
33 /// Instances of this type are always reference-counted, that is, a call to
34 /// `fwnode_handle_get` ensures that the allocation remains valid at least until
35 /// the matching call to `fwnode_handle_put`.
36 #[repr(transparent)]
37 pub struct FwNode(Opaque<bindings::fwnode_handle>);
38 
39 impl FwNode {
40     /// # Safety
41     ///
42     /// Callers must ensure that:
43     /// - The reference count was incremented at least once.
44     /// - They relinquish that increment. That is, if there is only one
45     ///   increment, callers must not use the underlying object anymore -- it is
46     ///   only safe to do so via the newly created `ARef<FwNode>`.
47     unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> {
48         // SAFETY: As per the safety requirements of this function:
49         // - `NonNull::new_unchecked`:
50         //   - `raw` is not null.
51         // - `ARef::from_raw`:
52         //   - `raw` has an incremented refcount.
53         //   - that increment is relinquished, i.e. it won't be decremented
54         //     elsewhere.
55         // CAST: It is safe to cast from a `*mut fwnode_handle` to
56         // `*mut FwNode`, because `FwNode` is  defined as a
57         // `#[repr(transparent)]` wrapper around `fwnode_handle`.
58         unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) }
59     }
60 
61     /// Obtain the raw `struct fwnode_handle *`.
62     pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle {
63         self.0.get()
64     }
65 
66     /// Returns `true` if `&self` is an OF node, `false` otherwise.
67     pub fn is_of_node(&self) -> bool {
68         // SAFETY: The type invariant of `Self` guarantees that `self.as_raw() is a pointer to a
69         // valid `struct fwnode_handle`.
70         unsafe { bindings::is_of_node(self.as_raw()) }
71     }
72 
73     /// Returns an object that implements [`Display`](fmt::Display) for
74     /// printing the name of a node.
75     ///
76     /// This is an alternative to the default `Display` implementation, which
77     /// prints the full path.
78     pub fn display_name(&self) -> impl fmt::Display + '_ {
79         struct FwNodeDisplayName<'a>(&'a FwNode);
80 
81         impl fmt::Display for FwNodeDisplayName<'_> {
82             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83                 // SAFETY: `self` is valid by its type invariant.
84                 let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) };
85                 if name.is_null() {
86                     return Ok(());
87                 }
88                 // SAFETY:
89                 // - `fwnode_get_name` returns null or a valid C string.
90                 // - `name` was checked to be non-null.
91                 let name = unsafe { CStr::from_char_ptr(name) };
92                 fmt::Display::fmt(name, f)
93             }
94         }
95 
96         FwNodeDisplayName(self)
97     }
98 
99     /// Checks if property is present or not.
100     pub fn property_present(&self, name: &CStr) -> bool {
101         // SAFETY: By the invariant of `CStr`, `name` is null-terminated.
102         unsafe { bindings::fwnode_property_present(self.as_raw().cast_const(), name.as_char_ptr()) }
103     }
104 
105     /// Returns firmware property `name` boolean value.
106     pub fn property_read_bool(&self, name: &CStr) -> bool {
107         // SAFETY:
108         // - `name` is non-null and null-terminated.
109         // - `self.as_raw()` is valid because `self` is valid.
110         unsafe { bindings::fwnode_property_read_bool(self.as_raw(), name.as_char_ptr()) }
111     }
112 
113     /// Returns the index of matching string `match_str` for firmware string
114     /// property `name`.
115     pub fn property_match_string(&self, name: &CStr, match_str: &CStr) -> Result<usize> {
116         // SAFETY:
117         // - `name` and `match_str` are non-null and null-terminated.
118         // - `self.as_raw` is valid because `self` is valid.
119         let ret = unsafe {
120             bindings::fwnode_property_match_string(
121                 self.as_raw(),
122                 name.as_char_ptr(),
123                 match_str.as_char_ptr(),
124             )
125         };
126         to_result(ret)?;
127         Ok(ret as usize)
128     }
129 
130     /// Returns firmware property `name` integer array values in a [`KVec`].
131     pub fn property_read_array_vec<'fwnode, 'name, T: PropertyInt>(
132         &'fwnode self,
133         name: &'name CStr,
134         len: usize,
135     ) -> Result<PropertyGuard<'fwnode, 'name, KVec<T>>> {
136         let mut val: KVec<T> = KVec::with_capacity(len, GFP_KERNEL)?;
137 
138         let res = T::read_array_from_fwnode_property(self, name, val.spare_capacity_mut());
139         let res = match res {
140             Ok(_) => {
141                 // SAFETY:
142                 // - `len` is equal to `val.capacity - val.len`, because
143                 //   `val.capacity` is `len` and `val.len` is zero.
144                 // - All elements within the interval [`0`, `len`) were initialized
145                 //   by `read_array_from_fwnode_property`.
146                 unsafe { val.inc_len(len) }
147                 Ok(val)
148             }
149             Err(e) => Err(e),
150         };
151         Ok(PropertyGuard {
152             inner: res,
153             fwnode: self,
154             name,
155         })
156     }
157 
158     /// Returns integer array length for firmware property `name`.
159     pub fn property_count_elem<T: PropertyInt>(&self, name: &CStr) -> Result<usize> {
160         T::read_array_len_from_fwnode_property(self, name)
161     }
162 
163     /// Returns the value of firmware property `name`.
164     ///
165     /// This method is generic over the type of value to read. The types that
166     /// can be read are strings, integers and arrays of integers.
167     ///
168     /// Reading a [`KVec`] of integers is done with the separate
169     /// method [`Self::property_read_array_vec`], because it takes an
170     /// additional `len` argument.
171     ///
172     /// Reading a boolean is done with the separate method
173     /// [`Self::property_read_bool`], because this operation is infallible.
174     ///
175     /// For more precise documentation about what types can be read, see
176     /// the [implementors of Property][Property#implementors] and [its
177     /// implementations on foreign types][Property#foreign-impls].
178     ///
179     /// # Examples
180     ///
181     /// ```
182     /// # use kernel::{device::{Device, property::FwNode}, str::CString};
183     /// fn examples(dev: &Device) -> Result {
184     ///     let fwnode = dev.fwnode().ok_or(ENOENT)?;
185     ///     let b: u32 = fwnode.property_read(c"some-number").required_by(dev)?;
186     ///     if let Some(s) = fwnode.property_read::<CString>(c"some-str").optional() {
187     ///         // ...
188     ///     }
189     ///     Ok(())
190     /// }
191     /// ```
192     pub fn property_read<'fwnode, 'name, T: Property>(
193         &'fwnode self,
194         name: &'name CStr,
195     ) -> PropertyGuard<'fwnode, 'name, T> {
196         PropertyGuard {
197             inner: T::read_from_fwnode_property(self, name),
198             fwnode: self,
199             name,
200         }
201     }
202 
203     /// Returns first matching named child node handle.
204     pub fn get_child_by_name(&self, name: &CStr) -> Option<ARef<Self>> {
205         // SAFETY: `self` and `name` are valid by their type invariants.
206         let child =
207             unsafe { bindings::fwnode_get_named_child_node(self.as_raw(), name.as_char_ptr()) };
208         if child.is_null() {
209             return None;
210         }
211         // SAFETY:
212         // - `fwnode_get_named_child_node` returns a pointer with its refcount
213         //   incremented.
214         // - That increment is relinquished, i.e. the underlying object is not
215         //   used anymore except via the newly created `ARef`.
216         Some(unsafe { Self::from_raw(child) })
217     }
218 
219     /// Returns an iterator over a node's children.
220     pub fn children<'a>(&'a self) -> impl Iterator<Item = ARef<FwNode>> + 'a {
221         let mut prev: Option<ARef<FwNode>> = None;
222 
223         core::iter::from_fn(move || {
224             let prev_ptr = match prev.take() {
225                 None => ptr::null_mut(),
226                 Some(prev) => {
227                     // We will pass `prev` to `fwnode_get_next_child_node`,
228                     // which decrements its refcount, so we use
229                     // `ARef::into_raw` to avoid decrementing the refcount
230                     // twice.
231                     let prev = ARef::into_raw(prev);
232                     prev.as_ptr().cast()
233                 }
234             };
235             // SAFETY:
236             // - `self.as_raw()` is valid by its type invariant.
237             // - `prev_ptr` may be null, which is allowed and corresponds to
238             //   getting the first child. Otherwise, `prev_ptr` is valid, as it
239             //   is the stored return value from the previous invocation.
240             // - `prev_ptr` has its refount incremented.
241             // - The increment of `prev_ptr` is relinquished, i.e. the
242             //   underlying object won't be used anymore.
243             let next = unsafe { bindings::fwnode_get_next_child_node(self.as_raw(), prev_ptr) };
244             if next.is_null() {
245                 return None;
246             }
247             // SAFETY:
248             // - `next` is valid because `fwnode_get_next_child_node` returns a
249             //   pointer with its refcount incremented.
250             // - That increment is relinquished, i.e. the underlying object
251             //   won't be used anymore, except via the newly created
252             //   `ARef<Self>`.
253             let next = unsafe { FwNode::from_raw(next) };
254             prev = Some(next.clone());
255             Some(next)
256         })
257     }
258 
259     /// Finds a reference with arguments.
260     pub fn property_get_reference_args(
261         &self,
262         prop: &CStr,
263         nargs: NArgs<'_>,
264         index: u32,
265     ) -> Result<FwNodeReferenceArgs> {
266         let mut out_args = FwNodeReferenceArgs::default();
267 
268         let (nargs_prop, nargs) = match nargs {
269             NArgs::Prop(nargs_prop) => (nargs_prop.as_char_ptr(), 0),
270             NArgs::N(nargs) => (ptr::null(), nargs),
271         };
272 
273         // SAFETY:
274         // - `self.0.get()` is valid.
275         // - `prop.as_char_ptr()` is valid and zero-terminated.
276         // - `nargs_prop` is valid and zero-terminated if `nargs`
277         //   is zero, otherwise it is allowed to be a null-pointer.
278         // - The function upholds the type invariants of `out_args`,
279         //   namely:
280         //   - It may fill the field `fwnode` with a valid pointer,
281         //     in which case its refcount is incremented.
282         //   - It may modify the field `nargs`, in which case it
283         //     initializes at least as many elements in `args`.
284         let ret = unsafe {
285             bindings::fwnode_property_get_reference_args(
286                 self.0.get(),
287                 prop.as_char_ptr(),
288                 nargs_prop,
289                 nargs,
290                 index,
291                 &mut out_args.0,
292             )
293         };
294         to_result(ret)?;
295 
296         Ok(out_args)
297     }
298 }
299 
300 /// The number of arguments to request [`FwNodeReferenceArgs`].
301 pub enum NArgs<'a> {
302     /// The name of the property of the reference indicating the number of
303     /// arguments.
304     Prop(&'a CStr),
305     /// The known number of arguments.
306     N(u32),
307 }
308 
309 /// The return value of [`FwNode::property_get_reference_args`].
310 ///
311 /// This structure represents the Rust abstraction for a C
312 /// `struct fwnode_reference_args` which was initialized by the C side.
313 ///
314 /// # Invariants
315 ///
316 /// If the field `fwnode` is valid, it owns an increment of its refcount.
317 ///
318 /// The field `args` contains at least as many initialized elements as indicated
319 /// by the field `nargs`.
320 #[repr(transparent)]
321 #[derive(Default)]
322 pub struct FwNodeReferenceArgs(bindings::fwnode_reference_args);
323 
324 impl Drop for FwNodeReferenceArgs {
325     fn drop(&mut self) {
326         if !self.0.fwnode.is_null() {
327             // SAFETY:
328             // - By the type invariants of `FwNodeReferenceArgs`, its field
329             //   `fwnode` owns an increment of its refcount.
330             // - That increment is relinquished. The underlying object won't be
331             //   used anymore because we are dropping it.
332             let _ = unsafe { FwNode::from_raw(self.0.fwnode) };
333         }
334     }
335 }
336 
337 impl FwNodeReferenceArgs {
338     /// Returns the slice of reference arguments.
339     pub fn as_slice(&self) -> &[u64] {
340         // SAFETY: As per the safety invariant of `FwNodeReferenceArgs`, `nargs`
341         // is the minimum number of elements in `args` that is valid.
342         unsafe { core::slice::from_raw_parts(self.0.args.as_ptr(), self.0.nargs as usize) }
343     }
344 
345     /// Returns the number of reference arguments.
346     pub fn len(&self) -> usize {
347         self.0.nargs as usize
348     }
349 
350     /// Returns `true` if there are no reference arguments.
351     pub fn is_empty(&self) -> bool {
352         self.0.nargs == 0
353     }
354 }
355 
356 impl fmt::Debug for FwNodeReferenceArgs {
357     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358         write!(f, "{:?}", self.as_slice())
359     }
360 }
361 
362 // SAFETY: Instances of `FwNode` are always reference-counted.
363 unsafe impl crate::sync::aref::AlwaysRefCounted for FwNode {
364     fn inc_ref(&self) {
365         // SAFETY: The existence of a shared reference guarantees that the
366         // refcount is non-zero.
367         unsafe { bindings::fwnode_handle_get(self.as_raw()) };
368     }
369 
370     unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
371         // SAFETY: The safety requirements guarantee that the refcount is
372         // non-zero.
373         unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) }
374     }
375 }
376 
377 enum Node<'a> {
378     Borrowed(&'a FwNode),
379     Owned(ARef<FwNode>),
380 }
381 
382 impl fmt::Display for FwNode {
383     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384         // The logic here is the same as the one in lib/vsprintf.c
385         // (fwnode_full_name_string).
386 
387         // SAFETY: `self.as_raw()` is valid by its type invariant.
388         let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) };
389 
390         for depth in (0..=num_parents).rev() {
391             let fwnode = if depth == 0 {
392                 Node::Borrowed(self)
393             } else {
394                 // SAFETY: `self.as_raw()` is valid.
395                 let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) };
396                 // SAFETY:
397                 // - The depth passed to `fwnode_get_nth_parent` is
398                 //   within the valid range, so the returned pointer is
399                 //   not null.
400                 // - The reference count was incremented by
401                 //   `fwnode_get_nth_parent`.
402                 // - That increment is relinquished to
403                 //   `FwNode::from_raw`.
404                 Node::Owned(unsafe { FwNode::from_raw(ptr) })
405             };
406             // Take a reference to the owned or borrowed `FwNode`.
407             let fwnode: &FwNode = match &fwnode {
408                 Node::Borrowed(f) => f,
409                 Node::Owned(f) => f,
410             };
411 
412             // SAFETY: `fwnode` is valid by its type invariant.
413             let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) };
414             if !prefix.is_null() {
415                 // SAFETY: `fwnode_get_name_prefix` returns null or a
416                 // valid C string.
417                 let prefix = unsafe { CStr::from_char_ptr(prefix) };
418                 fmt::Display::fmt(prefix, f)?;
419             }
420             fmt::Display::fmt(&fwnode.display_name(), f)?;
421         }
422 
423         Ok(())
424     }
425 }
426 
427 /// Implemented for types that can be read as properties.
428 ///
429 /// This is implemented for strings, integers and arrays of integers. It's used
430 /// to make [`FwNode::property_read`] generic over the type of property being
431 /// read. There are also two dedicated methods to read other types, because they
432 /// require more specialized function signatures:
433 /// - [`property_read_bool`](FwNode::property_read_bool)
434 /// - [`property_read_array_vec`](FwNode::property_read_array_vec)
435 ///
436 /// It must be public, because it appears in the signatures of other public
437 /// functions, but its methods shouldn't be used outside the kernel crate.
438 pub trait Property: Sized + Sealed {
439     /// Used to make [`FwNode::property_read`] generic.
440     fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self>;
441 }
442 
443 impl Sealed for CString {}
444 
445 impl Property for CString {
446     fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
447         let mut str: *mut u8 = ptr::null_mut();
448         let pstr: *mut _ = &mut str;
449 
450         // SAFETY:
451         // - `name` is non-null and null-terminated.
452         // - `fwnode.as_raw` is valid because `fwnode` is valid.
453         let ret = unsafe {
454             bindings::fwnode_property_read_string(fwnode.as_raw(), name.as_char_ptr(), pstr.cast())
455         };
456         to_result(ret)?;
457 
458         // SAFETY:
459         // - `pstr` is a valid pointer to a NUL-terminated C string.
460         // - It is valid for at least as long as `fwnode`, but it's only used
461         //   within the current function.
462         // - The memory it points to is not mutated during that time.
463         let str = unsafe { CStr::from_char_ptr(*pstr) };
464         Ok(str.try_into()?)
465     }
466 }
467 
468 /// Implemented for all integers that can be read as properties.
469 ///
470 /// This helper trait is needed on top of the existing [`Property`]
471 /// trait to associate the integer types of various sizes with their
472 /// corresponding `fwnode_property_read_*_array` functions.
473 ///
474 /// It must be public, because it appears in the signatures of other public
475 /// functions, but its methods shouldn't be used outside the kernel crate.
476 pub trait PropertyInt: Copy + Sealed {
477     /// Reads a property array.
478     fn read_array_from_fwnode_property<'a>(
479         fwnode: &FwNode,
480         name: &CStr,
481         out: &'a mut [MaybeUninit<Self>],
482     ) -> Result<&'a mut [Self]>;
483 
484     /// Reads the length of a property array.
485     fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize>;
486 }
487 // This macro generates implementations of the traits `Property` and
488 // `PropertyInt` for integers of various sizes. Its input is a list
489 // of pairs separated by commas. The first element of the pair is the
490 // type of the integer, the second one is the name of its corresponding
491 // `fwnode_property_read_*_array` function.
492 macro_rules! impl_property_for_int {
493     ($($int:ty: $f:ident),* $(,)?) => { $(
494         impl Sealed for $int {}
495         impl<const N: usize> Sealed for [$int; N] {}
496 
497         impl PropertyInt for $int {
498             fn read_array_from_fwnode_property<'a>(
499                 fwnode: &FwNode,
500                 name: &CStr,
501                 out: &'a mut [MaybeUninit<Self>],
502             ) -> Result<&'a mut [Self]> {
503                 // SAFETY:
504                 // - `fwnode`, `name` and `out` are all valid by their type
505                 //   invariants.
506                 // - `out.len()` is a valid bound for the memory pointed to by
507                 //   `out.as_mut_ptr()`.
508                 // CAST: It's ok to cast from `*mut MaybeUninit<$int>` to a
509                 // `*mut $int` because they have the same memory layout.
510                 let ret = unsafe {
511                     bindings::$f(
512                         fwnode.as_raw(),
513                         name.as_char_ptr(),
514                         out.as_mut_ptr().cast(),
515                         out.len(),
516                     )
517                 };
518                 to_result(ret)?;
519                 // SAFETY: Transmuting from `&'a mut [MaybeUninit<Self>]` to
520                 // `&'a mut [Self]` is sound, because the previous call to a
521                 // `fwnode_property_read_*_array` function (which didn't fail)
522                 // fully initialized the slice.
523                 Ok(unsafe { core::mem::transmute::<&mut [MaybeUninit<Self>], &mut [Self]>(out) })
524             }
525 
526             fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize> {
527                 // SAFETY:
528                 // - `fwnode` and `name` are valid by their type invariants.
529                 // - It's ok to pass a null pointer to the
530                 //   `fwnode_property_read_*_array` functions if `nval` is zero.
531                 //   This will return the length of the array.
532                 let ret = unsafe {
533                     bindings::$f(
534                         fwnode.as_raw(),
535                         name.as_char_ptr(),
536                         ptr::null_mut(),
537                         0,
538                     )
539                 };
540                 to_result(ret)?;
541                 Ok(ret as usize)
542             }
543         }
544 
545         impl Property for $int {
546             fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
547                 let val: [_; 1] = <[$int; 1]>::read_from_fwnode_property(fwnode, name)?;
548                 Ok(val[0])
549             }
550         }
551 
552         impl<const N: usize> Property for [$int; N] {
553             fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
554                 let mut val: [MaybeUninit<$int>; N] = [const { MaybeUninit::uninit() }; N];
555 
556                 <$int>::read_array_from_fwnode_property(fwnode, name, &mut val)?;
557 
558                 // SAFETY: `val` is always initialized when
559                 // `fwnode_property_read_*_array` is successful.
560                 Ok(val.map(|v| unsafe { v.assume_init() }))
561             }
562         }
563     )* };
564 }
565 impl_property_for_int! {
566     u8: fwnode_property_read_u8_array,
567     u16: fwnode_property_read_u16_array,
568     u32: fwnode_property_read_u32_array,
569     u64: fwnode_property_read_u64_array,
570     i8: fwnode_property_read_u8_array,
571     i16: fwnode_property_read_u16_array,
572     i32: fwnode_property_read_u32_array,
573     i64: fwnode_property_read_u64_array,
574 }
575 
576 /// A helper for reading device properties.
577 ///
578 /// Use [`Self::required_by`] if a missing property is considered a bug and
579 /// [`Self::optional`] otherwise.
580 ///
581 /// For convenience, [`Self::or`] and [`Self::or_default`] are provided.
582 pub struct PropertyGuard<'fwnode, 'name, T> {
583     /// The result of reading the property.
584     inner: Result<T>,
585     /// The fwnode of the property, used for logging in the "required" case.
586     fwnode: &'fwnode FwNode,
587     /// The name of the property, used for logging in the "required" case.
588     name: &'name CStr,
589 }
590 
591 impl<T> PropertyGuard<'_, '_, T> {
592     /// Access the property, indicating it is required.
593     ///
594     /// If the property is not present, the error is automatically logged. If a
595     /// missing property is not an error, use [`Self::optional`] instead. The
596     /// device is required to associate the log with it.
597     pub fn required_by(self, dev: &super::Device) -> Result<T> {
598         if self.inner.is_err() {
599             dev_err!(
600                 dev,
601                 "{}: property '{}' is missing\n",
602                 self.fwnode,
603                 self.name
604             );
605         }
606         self.inner
607     }
608 
609     /// Access the property, indicating it is optional.
610     ///
611     /// In contrast to [`Self::required_by`], no error message is logged if
612     /// the property is not present.
613     pub fn optional(self) -> Option<T> {
614         self.inner.ok()
615     }
616 
617     /// Access the property or the specified default value.
618     ///
619     /// Do not pass a sentinel value as default to detect a missing property.
620     /// Use [`Self::required_by`] or [`Self::optional`] instead.
621     pub fn or(self, default: T) -> T {
622         self.inner.unwrap_or(default)
623     }
624 }
625 
626 impl<T: Default> PropertyGuard<'_, '_, T> {
627     /// Access the property or a default value.
628     ///
629     /// Use [`Self::or`] to specify a custom default value.
630     pub fn or_default(self) -> T {
631         self.inner.unwrap_or_default()
632     }
633 }
634