Path: blob/master/rust/kernel/debugfs/callback_adapters.rs
29266 views
// SPDX-License-Identifier: GPL-2.01// Copyright (C) 2025 Google LLC.23//! Adapters which allow the user to supply a write or read implementation as a value rather4//! than a trait implementation. If provided, it will override the trait implementation.56use super::{Reader, Writer};7use crate::prelude::*;8use crate::uaccess::UserSliceReader;9use core::fmt;10use core::fmt::Formatter;11use core::marker::PhantomData;12use core::ops::Deref;1314/// # Safety15///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 {19type Inner;20}2122/// 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/// # Invariants28///29/// If an instance for `WritableAdapter<_, W>` is constructed, `W` is inhabited.30#[repr(transparent)]31pub(crate) struct WritableAdapter<D, W> {32inner: D,33_writer: PhantomData<W>,34}3536// SAFETY: Stripping off the adapter only removes constraints37unsafe impl<D, W> Adapter for WritableAdapter<D, W> {38type Inner = D;39}4041impl<D: Writer, W> Writer for WritableAdapter<D, W> {42fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {43self.inner.write(fmt)44}45}4647impl<D: Deref, W> Reader for WritableAdapter<D, W>48where49W: Fn(&D::Target, &mut UserSliceReader) -> Result + Send + Sync + 'static,50{51fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {52// SAFETY: WritableAdapter<_, W> can only be constructed if W is inhabited53let w: &W = unsafe { materialize_zst() };54w(self.inner.deref(), reader)55}56}5758/// Adapter to implement `Writer` via a callback with the same representation as `T`.59///60/// # Invariants61///62/// If an instance for `FormatAdapter<_, F>` is constructed, `F` is inhabited.63#[repr(transparent)]64pub(crate) struct FormatAdapter<D, F> {65inner: D,66_formatter: PhantomData<F>,67}6869impl<D, F> Deref for FormatAdapter<D, F> {70type Target = D;71fn deref(&self) -> &D {72&self.inner73}74}7576impl<D, F> Writer for FormatAdapter<D, F>77where78F: Fn(&D, &mut Formatter<'_>) -> fmt::Result + 'static,79{80fn write(&self, fmt: &mut Formatter<'_>) -> fmt::Result {81// SAFETY: FormatAdapter<_, F> can only be constructed if F is inhabited82let f: &F = unsafe { materialize_zst() };83f(&self.inner, fmt)84}85}8687// SAFETY: Stripping off the adapter only removes constraints88unsafe impl<D, F> Adapter for FormatAdapter<D, F> {89type Inner = D;90}9192#[repr(transparent)]93pub(crate) struct NoWriter<D> {94inner: D,95}9697// SAFETY: Stripping off the adapter only removes constraints98unsafe impl<D> Adapter for NoWriter<D> {99type Inner = D;100}101102impl<D> Deref for NoWriter<D> {103type Target = D;104fn deref(&self) -> &D {105&self.inner106}107}108109/// For types with a unique value, produce a static reference to it.110///111/// # Safety112///113/// The caller asserts that F is inhabited114unsafe fn materialize_zst<F>() -> &'static F {115const { assert!(core::mem::size_of::<F>() == 0) };116let 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 the118// assertion above. The type is also inhabited, by the caller's assertion. This means119// we can materialize it.120unsafe { zst_dangle.as_ref() }121}122123124