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;