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