Path: blob/master/rust/kernel/debugfs/callback_adapters.rs
49000 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::fmt;8use crate::prelude::*;9use crate::uaccess::UserSliceReader;10use core::marker::PhantomData;11use core::ops::Deref;1213/// # Safety14///15/// To implement this trait, it must be safe to cast a `&Self` to a `&Inner`.16/// It is intended for use in unstacking adapters out of `FileOps` backings.17pub(crate) unsafe trait Adapter {18type Inner;19}2021/// Adapter to implement `Reader` via a callback with the same representation as `T`.22///23/// * Layer it on top of `WriterAdapter` if you want to add a custom callback for `write`.24/// * Layer it on top of `NoWriter` to pass through any support present on the underlying type.25///26/// # Invariants27///28/// If an instance for `WritableAdapter<_, W>` is constructed, `W` is inhabited.29#[repr(transparent)]30pub(crate) struct WritableAdapter<D, W> {31inner: D,32_writer: PhantomData<W>,33}3435// SAFETY: Stripping off the adapter only removes constraints36unsafe impl<D, W> Adapter for WritableAdapter<D, W> {37type Inner = D;38}3940impl<D: Writer, W> Writer for WritableAdapter<D, W> {41fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {42self.inner.write(fmt)43}44}4546impl<D: Deref, W> Reader for WritableAdapter<D, W>47where48W: Fn(&D::Target, &mut UserSliceReader) -> Result + Send + Sync + 'static,49{50fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {51// SAFETY: WritableAdapter<_, W> can only be constructed if W is inhabited52let w: &W = unsafe { materialize_zst() };53w(self.inner.deref(), reader)54}55}5657/// Adapter to implement `Writer` via a callback with the same representation as `T`.58///59/// # Invariants60///61/// If an instance for `FormatAdapter<_, F>` is constructed, `F` is inhabited.62#[repr(transparent)]63pub(crate) struct FormatAdapter<D, F> {64inner: D,65_formatter: PhantomData<F>,66}6768impl<D, F> Deref for FormatAdapter<D, F> {69type Target = D;70fn deref(&self) -> &D {71&self.inner72}73}7475impl<D, F> Writer for FormatAdapter<D, F>76where77F: Fn(&D, &mut fmt::Formatter<'_>) -> fmt::Result + 'static,78{79fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {80// SAFETY: FormatAdapter<_, F> can only be constructed if F is inhabited81let f: &F = unsafe { materialize_zst() };82f(&self.inner, fmt)83}84}8586// SAFETY: Stripping off the adapter only removes constraints87unsafe impl<D, F> Adapter for FormatAdapter<D, F> {88type Inner = D;89}9091#[repr(transparent)]92pub(crate) struct NoWriter<D> {93inner: D,94}9596// SAFETY: Stripping off the adapter only removes constraints97unsafe impl<D> Adapter for NoWriter<D> {98type Inner = D;99}100101impl<D> Deref for NoWriter<D> {102type Target = D;103fn deref(&self) -> &D {104&self.inner105}106}107108/// For types with a unique value, produce a static reference to it.109///110/// # Safety111///112/// The caller asserts that F is inhabited113unsafe fn materialize_zst<F>() -> &'static F {114const { assert!(core::mem::size_of::<F>() == 0) };115let zst_dangle: core::ptr::NonNull<F> = core::ptr::NonNull::dangling();116// SAFETY: While the pointer is dangling, it is a dangling pointer to a ZST, based on the117// assertion above. The type is also inhabited, by the caller's assertion. This means118// we can materialize it.119unsafe { zst_dangle.as_ref() }120}121122123