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