11use std:: { borrow:: Borrow , ops:: Deref } ;
22
3+ use crate :: sync:: Lrc ;
34// Use our fake Send/Sync traits when on not parallel compiler,
45// so that `OwnedSlice` only implements/requires Send/Sync
56// for parallel compiler builds.
67use crate :: sync:: { Send , Sync } ;
78
89/// An owned slice.
910///
10- /// This is similar to `Box <[u8]>` but allows slicing and using anything as the
11+ /// This is similar to `Lrc <[u8]>` but allows slicing and using anything as the
1112/// backing buffer.
1213///
1314/// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
1617///
1718/// This is essentially a replacement for `owning_ref` which is a lot simpler
1819/// and even sound! 🌸
20+ #[ derive( Clone ) ]
1921pub struct OwnedSlice {
2022 /// This is conceptually a `&'self.owner [u8]`.
2123 bytes : * const [ u8 ] ,
@@ -31,7 +33,7 @@ pub struct OwnedSlice {
3133 // \/
3234 // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
3335 #[ expect( dead_code) ]
34- owner : Box < dyn Send + Sync > ,
36+ owner : Lrc < dyn Send + Sync > ,
3537}
3638
3739/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,23 +74,50 @@ where
7274 O : Send + Sync + ' static ,
7375 F : FnOnce ( & O ) -> Result < & [ u8 ] , E > ,
7476{
75- // We box the owner of the bytes, so it doesn't move.
77+ // We wrap the owner of the bytes in , so it doesn't move.
7678 //
7779 // Since the owner does not move and we don't access it in any way
78- // before drop , there is nothing that can invalidate the bytes pointer.
80+ // before dropping , there is nothing that can invalidate the bytes pointer.
7981 //
8082 // Thus, "extending" the lifetime of the reference returned from `F` is fine.
8183 // We pretend that we pass it a reference that lives as long as the returned slice.
8284 //
8385 // N.B. the HRTB on the `slicer` is important — without it the caller could provide
8486 // a short lived slice, unrelated to the owner.
8587
86- let owner = Box :: new ( owner) ;
88+ let owner = Lrc :: new ( owner) ;
8789 let bytes = slicer ( & * owner) ?;
8890
8991 Ok ( OwnedSlice { bytes, owner } )
9092}
9193
94+ impl OwnedSlice {
95+ /// Slice this slice by `slicer`.
96+ ///
97+ /// # Examples
98+ ///
99+ /// ```rust
100+ /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
101+ /// let vec = vec![1, 2, 3, 4];
102+ ///
103+ /// // Identical to slicing via `&v[1..3]` but produces an owned slice
104+ /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
105+ /// assert_eq!(&*slice, [1, 2, 3, 4]);
106+ ///
107+ /// let slice = slice.slice(|slice| &slice[1..][..2]);
108+ /// assert_eq!(&*slice, [2, 3]);
109+ /// ```
110+ ///
111+ pub fn slice ( self , slicer : impl FnOnce ( & [ u8 ] ) -> & [ u8 ] ) -> OwnedSlice {
112+ // This is basically identical to `try_slice_owned`,
113+ // `slicer` can only return slices of its argument or some static data,
114+ // both of which are valid while `owner` is alive.
115+
116+ let bytes = slicer ( & self ) ;
117+ OwnedSlice { bytes, ..self }
118+ }
119+ }
120+
92121impl Deref for OwnedSlice {
93122 type Target = [ u8 ] ;
94123
@@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
108137 }
109138}
110139
111- // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box <dyn Send + Sync>)`, which is `Send`
140+ // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc <dyn Send + Sync>)`, which is `Send`
112141#[ cfg( parallel_compiler) ]
113142unsafe impl Send for OwnedSlice { }
114143
115- // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box <dyn Send + Sync>)`, which is `Sync`
144+ // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc <dyn Send + Sync>)`, which is `Sync`
116145#[ cfg( parallel_compiler) ]
117146unsafe impl Sync for OwnedSlice { }
118147
0 commit comments