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