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