rustc_data_structures/
owned_slice.rs

1use std::borrow::Borrow;
2use std::ops::Deref;
3use std::sync::Arc;
4
5/// An owned slice.
6///
7/// This is similar to `Arc<[u8]>` but allows slicing and using anything as the
8/// backing buffer.
9///
10/// See [`slice_owned`] for `OwnedSlice` construction and examples.
11///
12/// ---------------------------------------------------------------------------
13///
14/// This is essentially a replacement for `owning_ref` which is a lot simpler
15/// and even sound! 🌸
16#[derive(Clone)]
17pub struct OwnedSlice {
18    /// This is conceptually a `&'self.owner [u8]`.
19    bytes: *const [u8],
20
21    // +---------------------------------------+
22    // | We expect `dead_code` lint here,      |
23    // | because we don't want to accidentally |
24    // | touch the owner — otherwise the owner |
25    // | could invalidate out `bytes` pointer  |
26    // |                                       |
27    // | so be quiet                           |
28    // +----+  +-------------------------------+
29    //       \/
30    //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
31    #[expect(dead_code)]
32    owner: Arc<dyn Send + Sync>,
33}
34
35/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
36///
37/// ## Examples
38///
39/// ```rust
40/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
41/// let vec = vec![1, 2, 3, 4];
42///
43/// // Identical to slicing via `&v[1..3]` but produces an owned slice
44/// let slice: OwnedSlice = slice_owned(vec, |v| &v[1..3]);
45/// assert_eq!(&*slice, [2, 3]);
46/// ```
47///
48/// ```rust
49/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
50/// # use std::ops::Deref;
51/// let vec = vec![1, 2, 3, 4];
52///
53/// // Identical to slicing via `&v[..]` but produces an owned slice
54/// let slice: OwnedSlice = slice_owned(vec, Deref::deref);
55/// assert_eq!(&*slice, [1, 2, 3, 4]);
56/// ```
57pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
58where
59    O: Send + Sync + 'static,
60    F: FnOnce(&O) -> &[u8],
61{
62    try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
63}
64
65/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function that can fail.
66///
67/// See [`slice_owned`] for the infallible version.
68pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
69where
70    O: Send + Sync + 'static,
71    F: FnOnce(&O) -> Result<&[u8], E>,
72{
73    // We wrap the owner of the bytes in, so it doesn't move.
74    //
75    // Since the owner does not move and we don't access it in any way
76    // before dropping, there is nothing that can invalidate the bytes pointer.
77    //
78    // Thus, "extending" the lifetime of the reference returned from `F` is fine.
79    // We pretend that we pass it a reference that lives as long as the returned slice.
80    //
81    // N.B. the HRTB on the `slicer` is important — without it the caller could provide
82    // a short lived slice, unrelated to the owner.
83
84    let owner = Arc::new(owner);
85    let bytes = slicer(&*owner)?;
86
87    Ok(OwnedSlice { bytes, owner })
88}
89
90impl OwnedSlice {
91    /// Slice this slice by `slicer`.
92    ///
93    /// # Examples
94    ///
95    /// ```rust
96    /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
97    /// let vec = vec![1, 2, 3, 4];
98    ///
99    /// // Identical to slicing via `&v[1..3]` but produces an owned slice
100    /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
101    /// assert_eq!(&*slice, [1, 2, 3, 4]);
102    ///
103    /// let slice = slice.slice(|slice| &slice[1..][..2]);
104    /// assert_eq!(&*slice, [2, 3]);
105    /// ```
106    ///
107    pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
108        // This is basically identical to `try_slice_owned`,
109        // `slicer` can only return slices of its argument or some static data,
110        // both of which are valid while `owner` is alive.
111
112        let bytes = slicer(&self);
113        OwnedSlice { bytes, ..self }
114    }
115}
116
117impl Deref for OwnedSlice {
118    type Target = [u8];
119
120    #[inline]
121    fn deref(&self) -> &[u8] {
122        // Safety:
123        // `self.bytes` is valid per the construction in `slice_owned`
124        // (which is the only constructor)
125        unsafe { &*self.bytes }
126    }
127}
128
129impl Borrow<[u8]> for OwnedSlice {
130    #[inline]
131    fn borrow(&self) -> &[u8] {
132        self
133    }
134}
135
136// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
137unsafe impl Send for OwnedSlice {}
138
139// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
140unsafe impl Sync for OwnedSlice {}
141
142#[cfg(test)]
143mod tests;