mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 13:04:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			150 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use std::{borrow::Borrow, ops::Deref};
 | |
| 
 | |
| use crate::sync::Lrc;
 | |
| // Use our fake Send/Sync traits when on not parallel compiler,
 | |
| // so that `OwnedSlice` only implements/requires Send/Sync
 | |
| // for parallel compiler builds.
 | |
| use crate::sync::{Send, Sync};
 | |
| 
 | |
| /// An owned slice.
 | |
| ///
 | |
| /// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
 | |
| /// backing buffer.
 | |
| ///
 | |
| /// See [`slice_owned`] for `OwnedSlice` construction and examples.
 | |
| ///
 | |
| /// ---------------------------------------------------------------------------
 | |
| ///
 | |
| /// This is essentially a replacement for `owning_ref` which is a lot simpler
 | |
| /// and even sound! 🌸
 | |
| #[derive(Clone)]
 | |
| pub struct OwnedSlice {
 | |
|     /// This is conceptually a `&'self.owner [u8]`.
 | |
|     bytes: *const [u8],
 | |
| 
 | |
|     // +---------------------------------------+
 | |
|     // | We expect `dead_code` lint here,      |
 | |
|     // | because we don't want to accidentally |
 | |
|     // | touch the owner — otherwise the owner |
 | |
|     // | could invalidate out `bytes` pointer  |
 | |
|     // |                                       |
 | |
|     // | so be quiet                           |
 | |
|     // +----+  +-------------------------------+
 | |
|     //       \/
 | |
|     //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
 | |
|     #[expect(dead_code)]
 | |
|     owner: Lrc<dyn Send + Sync>,
 | |
| }
 | |
| 
 | |
| /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
 | |
| ///
 | |
| /// ## Examples
 | |
| ///
 | |
| /// ```rust
 | |
| /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
 | |
| /// let vec = vec![1, 2, 3, 4];
 | |
| ///
 | |
| /// // Identical to slicing via `&v[1..3]` but produces an owned slice
 | |
| /// let slice: OwnedSlice = slice_owned(vec, |v| &v[1..3]);
 | |
| /// assert_eq!(&*slice, [2, 3]);
 | |
| /// ```
 | |
| ///
 | |
| /// ```rust
 | |
| /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
 | |
| /// # use std::ops::Deref;
 | |
| /// let vec = vec![1, 2, 3, 4];
 | |
| ///
 | |
| /// // Identical to slicing via `&v[..]` but produces an owned slice
 | |
| /// let slice: OwnedSlice = slice_owned(vec, Deref::deref);
 | |
| /// assert_eq!(&*slice, [1, 2, 3, 4]);
 | |
| /// ```
 | |
| pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
 | |
| where
 | |
|     O: Send + Sync + 'static,
 | |
|     F: FnOnce(&O) -> &[u8],
 | |
| {
 | |
|     try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
 | |
| }
 | |
| 
 | |
| /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function that can fail.
 | |
| ///
 | |
| /// See [`slice_owned`] for the infallible version.
 | |
| pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
 | |
| where
 | |
|     O: Send + Sync + 'static,
 | |
|     F: FnOnce(&O) -> Result<&[u8], E>,
 | |
| {
 | |
|     // We wrap the owner of the bytes in, so it doesn't move.
 | |
|     //
 | |
|     // Since the owner does not move and we don't access it in any way
 | |
|     // before dropping, there is nothing that can invalidate the bytes pointer.
 | |
|     //
 | |
|     // Thus, "extending" the lifetime of the reference returned from `F` is fine.
 | |
|     // We pretend that we pass it a reference that lives as long as the returned slice.
 | |
|     //
 | |
|     // N.B. the HRTB on the `slicer` is important — without it the caller could provide
 | |
|     // a short lived slice, unrelated to the owner.
 | |
| 
 | |
|     let owner = Lrc::new(owner);
 | |
|     let bytes = slicer(&*owner)?;
 | |
| 
 | |
|     Ok(OwnedSlice { bytes, owner })
 | |
| }
 | |
| 
 | |
| impl OwnedSlice {
 | |
|     /// Slice this slice by `slicer`.
 | |
|     ///
 | |
|     /// # Examples
 | |
|     ///
 | |
|     /// ```rust
 | |
|     /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
 | |
|     /// let vec = vec![1, 2, 3, 4];
 | |
|     ///
 | |
|     /// // Identical to slicing via `&v[1..3]` but produces an owned slice
 | |
|     /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
 | |
|     /// assert_eq!(&*slice, [1, 2, 3, 4]);
 | |
|     ///
 | |
|     /// let slice = slice.slice(|slice| &slice[1..][..2]);
 | |
|     /// assert_eq!(&*slice, [2, 3]);
 | |
|     /// ```
 | |
|     ///
 | |
|     pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
 | |
|         // This is basically identical to `try_slice_owned`,
 | |
|         // `slicer` can only return slices of its argument or some static data,
 | |
|         // both of which are valid while `owner` is alive.
 | |
| 
 | |
|         let bytes = slicer(&self);
 | |
|         OwnedSlice { bytes, ..self }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Deref for OwnedSlice {
 | |
|     type Target = [u8];
 | |
| 
 | |
|     #[inline]
 | |
|     fn deref(&self) -> &[u8] {
 | |
|         // Safety:
 | |
|         // `self.bytes` is valid per the construction in `slice_owned`
 | |
|         // (which is the only constructor)
 | |
|         unsafe { &*self.bytes }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Borrow<[u8]> for OwnedSlice {
 | |
|     #[inline]
 | |
|     fn borrow(&self) -> &[u8] {
 | |
|         self
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
 | |
| #[cfg(parallel_compiler)]
 | |
| unsafe impl Send for OwnedSlice {}
 | |
| 
 | |
| // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
 | |
| #[cfg(parallel_compiler)]
 | |
| unsafe impl Sync for OwnedSlice {}
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests;
 | 
