File Index
Files and directories
Sign in
FILE

callback_adapters.rs

File preview with syntax highlighting.

linux-6.19.14/rust/kernel/debugfs/callback_adapters.rs RUST
  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::fmt;
  9use crate::prelude::*;
 10use crate::uaccess::UserSliceReader;
 11use core::marker::PhantomData;
 12use 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.
 18pub(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)]
 31pub(crate) struct WritableAdapter<D, W> {
 32    inner: D,
 33    _writer: PhantomData<W>,
 34}
 35
 36// SAFETY: Stripping off the adapter only removes constraints
 37unsafe impl<D, W> Adapter for WritableAdapter<D, W> {
 38    type Inner = D;
 39}
 40
 41impl<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
 47impl<D: Deref, W> Reader for WritableAdapter<D, W>
 48where
 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)]
 64pub(crate) struct FormatAdapter<D, F> {
 65    inner: D,
 66    _formatter: PhantomData<F>,
 67}
 68
 69impl<D, F> Deref for FormatAdapter<D, F> {
 70    type Target = D;
 71    fn deref(&self) -> &D {
 72        &self.inner
 73    }
 74}
 75
 76impl<D, F> Writer for FormatAdapter<D, F>
 77where
 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
 88unsafe impl<D, F> Adapter for FormatAdapter<D, F> {
 89    type Inner = D;
 90}
 91
 92#[repr(transparent)]
 93pub(crate) struct NoWriter<D> {
 94    inner: D,
 95}
 96
 97// SAFETY: Stripping off the adapter only removes constraints
 98unsafe impl<D> Adapter for NoWriter<D> {
 99    type Inner = D;
100}
101
102impl<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
114unsafe 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}
~/ Read-only file preview.