xref: /linux/rust/kernel/debugfs/callback_adapters.rs (revision 0e947bc22b0bdac7f708a0c6856f5999baff7b5d)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2025 Google LLC.
3 
4 //! Adapters which allow the user to supply a write or read implementation as a value rather
5 //! than a trait implementation. If provided, it will override the trait implementation.
6 
7 use super::{Reader, Writer};
8 use crate::fmt;
9 use crate::prelude::*;
10 use crate::uaccess::UserSliceReader;
11 use core::marker::PhantomData;
12 use core::ops::Deref;
13 
14 /// # Safety
15 ///
16 /// To implement this trait, it must be safe to cast a `&Self` to a `&Inner`.
17 /// It is intended for use in unstacking adapters out of `FileOps` backings.
18 pub(crate) unsafe trait Adapter {
19     type Inner;
20 }
21 
22 /// Adapter to implement `Reader` via a callback with the same representation as `T`.
23 ///
24 /// * Layer it on top of `WriterAdapter` if you want to add a custom callback for `write`.
25 /// * Layer it on top of `NoWriter` to pass through any support present on the underlying type.
26 ///
27 /// # Invariants
28 ///
29 /// If an instance for `WritableAdapter<_, W>` is constructed, `W` is inhabited.
30 #[repr(transparent)]
31 pub(crate) struct WritableAdapter<D, W> {
32     inner: D,
33     _writer: PhantomData<W>,
34 }
35 
36 // SAFETY: Stripping off the adapter only removes constraints
37 unsafe impl<D, W> Adapter for WritableAdapter<D, W> {
38     type Inner = D;
39 }
40 
41 impl<D: Writer, W> Writer for WritableAdapter<D, W> {
42     fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
43         self.inner.write(fmt)
44     }
45 }
46 
47 impl<D: Deref, W> Reader for WritableAdapter<D, W>
48 where
49     W: Fn(&D::Target, &mut UserSliceReader) -> Result + Send + Sync + 'static,
50 {
51     fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
52         // SAFETY: WritableAdapter<_, W> can only be constructed if W is inhabited
53         let w: &W = unsafe { materialize_zst() };
54         w(self.inner.deref(), reader)
55     }
56 }
57 
58 /// Adapter to implement `Writer` via a callback with the same representation as `T`.
59 ///
60 /// # Invariants
61 ///
62 /// If an instance for `FormatAdapter<_, F>` is constructed, `F` is inhabited.
63 #[repr(transparent)]
64 pub(crate) struct FormatAdapter<D, F> {
65     inner: D,
66     _formatter: PhantomData<F>,
67 }
68 
69 impl<D, F> Deref for FormatAdapter<D, F> {
70     type Target = D;
71     fn deref(&self) -> &D {
72         &self.inner
73     }
74 }
75 
76 impl<D, F> Writer for FormatAdapter<D, F>
77 where
78     F: Fn(&D, &mut fmt::Formatter<'_>) -> fmt::Result + 'static,
79 {
80     fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
81         // SAFETY: FormatAdapter<_, F> can only be constructed if F is inhabited
82         let f: &F = unsafe { materialize_zst() };
83         f(&self.inner, fmt)
84     }
85 }
86 
87 // SAFETY: Stripping off the adapter only removes constraints
88 unsafe impl<D, F> Adapter for FormatAdapter<D, F> {
89     type Inner = D;
90 }
91 
92 #[repr(transparent)]
93 pub(crate) struct NoWriter<D> {
94     inner: D,
95 }
96 
97 // SAFETY: Stripping off the adapter only removes constraints
98 unsafe impl<D> Adapter for NoWriter<D> {
99     type Inner = D;
100 }
101 
102 impl<D> Deref for NoWriter<D> {
103     type Target = D;
104     fn deref(&self) -> &D {
105         &self.inner
106     }
107 }
108 
109 /// For types with a unique value, produce a static reference to it.
110 ///
111 /// # Safety
112 ///
113 /// The caller asserts that F is inhabited
114 unsafe fn materialize_zst<F>() -> &'static F {
115     const { assert!(core::mem::size_of::<F>() == 0) };
116     let zst_dangle: core::ptr::NonNull<F> = core::ptr::NonNull::dangling();
117     // SAFETY: While the pointer is dangling, it is a dangling pointer to a ZST, based on the
118     // assertion above. The type is also inhabited, by the caller's assertion. This means
119     // we can materialize it.
120     unsafe { zst_dangle.as_ref() }
121 }
122