diff --git a/src/bytes.rs b/src/bytes.rs index 0b443c85b..6cf745dfd 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -535,6 +535,53 @@ impl Bytes { self.len -= by; self.ptr = self.ptr.add(by); } + + /// Creates a new `Bytes` from a raw pointer and a length. + /// + /// # Examples + /// To create a new `Bytes` where the start position and end position of the backing store are + /// aligned to 32-byte boundaries: + /// + /// ``` + /// use bytes::Bytes; + /// use std::alloc::{alloc, Layout, handle_alloc_error}; + /// + /// const LEN: usize = 64; + /// const ALIGN: usize = 32; + /// + /// let layout = Layout::from_size_align(LEN, ALIGN) + /// .expect("failed to create Layout!") + /// .pad_to_align(); + /// let ptr = unsafe { alloc(layout) }; + /// if ptr.is_null() { + /// handle_alloc_error(layout); + /// }; + /// + /// // (Not shown here: Pass `ptr` to code that will write data into the buffer. + /// // For example, pass `ptr` to a system call to load data from disk using `O_DIRECT`.) + /// + /// let buf = Bytes::from_raw_parts(ptr, layout.size()); + /// assert_eq!(buf.len(), layout.size()); + /// ``` + pub fn from_raw_parts(ptr: *const u8, len: usize) -> Self { + let ptr = ptr as *mut u8; + if ptr as usize & 0x1 == 0 { + let data = ptr_map(ptr, |addr| addr | KIND_VEC); + Bytes { + ptr, + len, + data: AtomicPtr::new(data.cast()), + vtable: &PROMOTABLE_EVEN_VTABLE, + } + } else { + Bytes { + ptr, + len, + data: AtomicPtr::new(ptr.cast()), + vtable: &PROMOTABLE_ODD_VTABLE, + } + } + } } // Vtable must enforce this behavior