kernel/debugfs/
callback_adapters.rs

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