Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/debugfs/callback_adapters.rs
49000 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::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
123