1
1
use std:: { borrow:: Borrow , ops:: Deref } ;
2
2
3
+ use crate :: sync:: Lrc ;
3
4
// Use our fake Send/Sync traits when on not parallel compiler,
4
5
// so that `OwnedSlice` only implements/requires Send/Sync
5
6
// for parallel compiler builds.
6
7
use crate :: sync:: { Send , Sync } ;
7
8
8
9
/// An owned slice.
9
10
///
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
11
12
/// backing buffer.
12
13
///
13
14
/// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
16
17
///
17
18
/// This is essentially a replacement for `owning_ref` which is a lot simpler
18
19
/// and even sound! 🌸
20
+ #[ derive( Clone ) ]
19
21
pub struct OwnedSlice {
20
22
/// This is conceptually a `&'self.owner [u8]`.
21
23
bytes : * const [ u8 ] ,
@@ -31,7 +33,7 @@ pub struct OwnedSlice {
31
33
// \/
32
34
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
33
35
#[ expect( dead_code) ]
34
- owner : Box < dyn Send + Sync > ,
36
+ owner : Lrc < dyn Send + Sync > ,
35
37
}
36
38
37
39
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,23 +74,50 @@ where
72
74
O : Send + Sync + ' static ,
73
75
F : FnOnce ( & O ) -> Result < & [ u8 ] , E > ,
74
76
{
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.
76
78
//
77
79
// 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.
79
81
//
80
82
// Thus, "extending" the lifetime of the reference returned from `F` is fine.
81
83
// We pretend that we pass it a reference that lives as long as the returned slice.
82
84
//
83
85
// N.B. the HRTB on the `slicer` is important — without it the caller could provide
84
86
// a short lived slice, unrelated to the owner.
85
87
86
- let owner = Box :: new ( owner) ;
88
+ let owner = Lrc :: new ( owner) ;
87
89
let bytes = slicer ( & * owner) ?;
88
90
89
91
Ok ( OwnedSlice { bytes, owner } )
90
92
}
91
93
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
+
92
121
impl Deref for OwnedSlice {
93
122
type Target = [ u8 ] ;
94
123
@@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
108
137
}
109
138
}
110
139
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`
112
141
#[ cfg( parallel_compiler) ]
113
142
unsafe impl Send for OwnedSlice { }
114
143
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`
116
145
#[ cfg( parallel_compiler) ]
117
146
unsafe impl Sync for OwnedSlice { }
118
147
0 commit comments