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