Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/debugfs/callback_adapters.rs
29266 views
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::prelude::*;
9
use crate::uaccess::UserSliceReader;
10
use core::fmt;
11
use core::fmt::Formatter;
12
use core::marker::PhantomData;
13
use 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.
19
pub(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)]
32
pub(crate) struct WritableAdapter<D, W> {
33
inner: D,
34
_writer: PhantomData<W>,
35
}
36
37
// SAFETY: Stripping off the adapter only removes constraints
38
unsafe impl<D, W> Adapter for WritableAdapter<D, W> {
39
type Inner = D;
40
}
41
42
impl<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
48
impl<D: Deref, W> Reader for WritableAdapter<D, W>
49
where
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)]
65
pub(crate) struct FormatAdapter<D, F> {
66
inner: D,
67
_formatter: PhantomData<F>,
68
}
69
70
impl<D, F> Deref for FormatAdapter<D, F> {
71
type Target = D;
72
fn deref(&self) -> &D {
73
&self.inner
74
}
75
}
76
77
impl<D, F> Writer for FormatAdapter<D, F>
78
where
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
89
unsafe impl<D, F> Adapter for FormatAdapter<D, F> {
90
type Inner = D;
91
}
92
93
#[repr(transparent)]
94
pub(crate) struct NoWriter<D> {
95
inner: D,
96
}
97
98
// SAFETY: Stripping off the adapter only removes constraints
99
unsafe impl<D> Adapter for NoWriter<D> {
100
type Inner = D;
101
}
102
103
impl<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
115
unsafe 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
}
123
124