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