1*40ecc494SMatthew Maurer // SPDX-License-Identifier: GPL-2.0 2*40ecc494SMatthew Maurer // Copyright (C) 2025 Google LLC. 3*40ecc494SMatthew Maurer 4*40ecc494SMatthew Maurer //! Adapters which allow the user to supply a write or read implementation as a value rather 5*40ecc494SMatthew Maurer //! than a trait implementation. If provided, it will override the trait implementation. 6*40ecc494SMatthew Maurer 7*40ecc494SMatthew Maurer use super::{Reader, Writer}; 8*40ecc494SMatthew Maurer use crate::prelude::*; 9*40ecc494SMatthew Maurer use crate::uaccess::UserSliceReader; 10*40ecc494SMatthew Maurer use core::fmt; 11*40ecc494SMatthew Maurer use core::fmt::Formatter; 12*40ecc494SMatthew Maurer use core::marker::PhantomData; 13*40ecc494SMatthew Maurer use core::ops::Deref; 14*40ecc494SMatthew Maurer 15*40ecc494SMatthew Maurer /// # Safety 16*40ecc494SMatthew Maurer /// 17*40ecc494SMatthew Maurer /// To implement this trait, it must be safe to cast a `&Self` to a `&Inner`. 18*40ecc494SMatthew Maurer /// It is intended for use in unstacking adapters out of `FileOps` backings. 19*40ecc494SMatthew Maurer pub(crate) unsafe trait Adapter { 20*40ecc494SMatthew Maurer type Inner; 21*40ecc494SMatthew Maurer } 22*40ecc494SMatthew Maurer 23*40ecc494SMatthew Maurer /// Adapter to implement `Reader` via a callback with the same representation as `T`. 24*40ecc494SMatthew Maurer /// 25*40ecc494SMatthew Maurer /// * Layer it on top of `WriterAdapter` if you want to add a custom callback for `write`. 26*40ecc494SMatthew Maurer /// * Layer it on top of `NoWriter` to pass through any support present on the underlying type. 27*40ecc494SMatthew Maurer /// 28*40ecc494SMatthew Maurer /// # Invariants 29*40ecc494SMatthew Maurer /// 30*40ecc494SMatthew Maurer /// If an instance for `WritableAdapter<_, W>` is constructed, `W` is inhabited. 31*40ecc494SMatthew Maurer #[repr(transparent)] 32*40ecc494SMatthew Maurer pub(crate) struct WritableAdapter<D, W> { 33*40ecc494SMatthew Maurer inner: D, 34*40ecc494SMatthew Maurer _writer: PhantomData<W>, 35*40ecc494SMatthew Maurer } 36*40ecc494SMatthew Maurer 37*40ecc494SMatthew Maurer // SAFETY: Stripping off the adapter only removes constraints 38*40ecc494SMatthew Maurer unsafe impl<D, W> Adapter for WritableAdapter<D, W> { 39*40ecc494SMatthew Maurer type Inner = D; 40*40ecc494SMatthew Maurer } 41*40ecc494SMatthew Maurer 42*40ecc494SMatthew Maurer impl<D: Writer, W> Writer for WritableAdapter<D, W> { 43*40ecc494SMatthew Maurer fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 44*40ecc494SMatthew Maurer self.inner.write(fmt) 45*40ecc494SMatthew Maurer } 46*40ecc494SMatthew Maurer } 47*40ecc494SMatthew Maurer 48*40ecc494SMatthew Maurer impl<D: Deref, W> Reader for WritableAdapter<D, W> 49*40ecc494SMatthew Maurer where 50*40ecc494SMatthew Maurer W: Fn(&D::Target, &mut UserSliceReader) -> Result + Send + Sync + 'static, 51*40ecc494SMatthew Maurer { 52*40ecc494SMatthew Maurer fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result { 53*40ecc494SMatthew Maurer // SAFETY: WritableAdapter<_, W> can only be constructed if W is inhabited 54*40ecc494SMatthew Maurer let w: &W = unsafe { materialize_zst() }; 55*40ecc494SMatthew Maurer w(self.inner.deref(), reader) 56*40ecc494SMatthew Maurer } 57*40ecc494SMatthew Maurer } 58*40ecc494SMatthew Maurer 59*40ecc494SMatthew Maurer /// Adapter to implement `Writer` via a callback with the same representation as `T`. 60*40ecc494SMatthew Maurer /// 61*40ecc494SMatthew Maurer /// # Invariants 62*40ecc494SMatthew Maurer /// 63*40ecc494SMatthew Maurer /// If an instance for `FormatAdapter<_, F>` is constructed, `F` is inhabited. 64*40ecc494SMatthew Maurer #[repr(transparent)] 65*40ecc494SMatthew Maurer pub(crate) struct FormatAdapter<D, F> { 66*40ecc494SMatthew Maurer inner: D, 67*40ecc494SMatthew Maurer _formatter: PhantomData<F>, 68*40ecc494SMatthew Maurer } 69*40ecc494SMatthew Maurer 70*40ecc494SMatthew Maurer impl<D, F> Deref for FormatAdapter<D, F> { 71*40ecc494SMatthew Maurer type Target = D; 72*40ecc494SMatthew Maurer fn deref(&self) -> &D { 73*40ecc494SMatthew Maurer &self.inner 74*40ecc494SMatthew Maurer } 75*40ecc494SMatthew Maurer } 76*40ecc494SMatthew Maurer 77*40ecc494SMatthew Maurer impl<D, F> Writer for FormatAdapter<D, F> 78*40ecc494SMatthew Maurer where 79*40ecc494SMatthew Maurer F: Fn(&D, &mut Formatter<'_>) -> fmt::Result + 'static, 80*40ecc494SMatthew Maurer { 81*40ecc494SMatthew Maurer fn write(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 82*40ecc494SMatthew Maurer // SAFETY: FormatAdapter<_, F> can only be constructed if F is inhabited 83*40ecc494SMatthew Maurer let f: &F = unsafe { materialize_zst() }; 84*40ecc494SMatthew Maurer f(&self.inner, fmt) 85*40ecc494SMatthew Maurer } 86*40ecc494SMatthew Maurer } 87*40ecc494SMatthew Maurer 88*40ecc494SMatthew Maurer // SAFETY: Stripping off the adapter only removes constraints 89*40ecc494SMatthew Maurer unsafe impl<D, F> Adapter for FormatAdapter<D, F> { 90*40ecc494SMatthew Maurer type Inner = D; 91*40ecc494SMatthew Maurer } 92*40ecc494SMatthew Maurer 93*40ecc494SMatthew Maurer #[repr(transparent)] 94*40ecc494SMatthew Maurer pub(crate) struct NoWriter<D> { 95*40ecc494SMatthew Maurer inner: D, 96*40ecc494SMatthew Maurer } 97*40ecc494SMatthew Maurer 98*40ecc494SMatthew Maurer // SAFETY: Stripping off the adapter only removes constraints 99*40ecc494SMatthew Maurer unsafe impl<D> Adapter for NoWriter<D> { 100*40ecc494SMatthew Maurer type Inner = D; 101*40ecc494SMatthew Maurer } 102*40ecc494SMatthew Maurer 103*40ecc494SMatthew Maurer impl<D> Deref for NoWriter<D> { 104*40ecc494SMatthew Maurer type Target = D; 105*40ecc494SMatthew Maurer fn deref(&self) -> &D { 106*40ecc494SMatthew Maurer &self.inner 107*40ecc494SMatthew Maurer } 108*40ecc494SMatthew Maurer } 109*40ecc494SMatthew Maurer 110*40ecc494SMatthew Maurer /// For types with a unique value, produce a static reference to it. 111*40ecc494SMatthew Maurer /// 112*40ecc494SMatthew Maurer /// # Safety 113*40ecc494SMatthew Maurer /// 114*40ecc494SMatthew Maurer /// The caller asserts that F is inhabited 115*40ecc494SMatthew Maurer unsafe fn materialize_zst<F>() -> &'static F { 116*40ecc494SMatthew Maurer const { assert!(core::mem::size_of::<F>() == 0) }; 117*40ecc494SMatthew Maurer let zst_dangle: core::ptr::NonNull<F> = core::ptr::NonNull::dangling(); 118*40ecc494SMatthew Maurer // SAFETY: While the pointer is dangling, it is a dangling pointer to a ZST, based on the 119*40ecc494SMatthew Maurer // assertion above. The type is also inhabited, by the caller's assertion. This means 120*40ecc494SMatthew Maurer // we can materialize it. 121*40ecc494SMatthew Maurer unsafe { zst_dangle.as_ref() } 122*40ecc494SMatthew Maurer } 123