Add `<*const T>::align_offset` and use it in `memchr`
This commit is contained in:
parent
1cdd68922d
commit
2787a285bd
|
@ -1381,38 +1381,7 @@ extern "rust-intrinsic" {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
#[cfg(stage0)]
|
||||||
/// Computes the byte offset that needs to be applied to `ptr` in order to
|
/// remove me after the next release
|
||||||
/// make it aligned to `align`.
|
|
||||||
/// If it is not possible to align `ptr`, the implementation returns
|
|
||||||
/// `usize::max_value()`.
|
|
||||||
///
|
|
||||||
/// There are no guarantees whatsover that offsetting the pointer will not
|
|
||||||
/// overflow or go beyond the allocation that `ptr` points into.
|
|
||||||
/// It is up to the caller to ensure that the returned offset is correct
|
|
||||||
/// in all terms other than alignment.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// Accessing adjacent `u8` as `u16`
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(core_intrinsics)]
|
|
||||||
/// # fn foo(n: usize) {
|
|
||||||
/// # use std::intrinsics::align_offset;
|
|
||||||
/// # use std::mem::align_of;
|
|
||||||
/// # unsafe {
|
|
||||||
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
|
|
||||||
/// let ptr = &x[n] as *const u8;
|
|
||||||
/// let offset = align_offset(ptr as *const (), align_of::<u16>());
|
|
||||||
/// if offset < x.len() - n - 1 {
|
|
||||||
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
|
|
||||||
/// assert_ne!(*u16_ptr, 500);
|
|
||||||
/// } else {
|
|
||||||
/// // while the pointer can be aligned via `offset`, it would point
|
|
||||||
/// // outside the allocation
|
|
||||||
/// }
|
|
||||||
/// # } }
|
|
||||||
/// ```
|
|
||||||
pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize {
|
pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize {
|
||||||
let offset = ptr as usize % align;
|
let offset = ptr as usize % align;
|
||||||
if offset == 0 {
|
if offset == 0 {
|
||||||
|
|
|
@ -1064,7 +1064,43 @@ impl<T: ?Sized> *const T {
|
||||||
copy_nonoverlapping(self, dest, count)
|
copy_nonoverlapping(self, dest, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the byte offset that needs to be applied in order to
|
||||||
|
/// make the pointer aligned to `align`.
|
||||||
|
/// If it is not possible to align the pointer, the implementation returns
|
||||||
|
/// `usize::max_value()`.
|
||||||
|
///
|
||||||
|
/// There are no guarantees whatsover that offsetting the pointer will not
|
||||||
|
/// overflow or go beyond the allocation that the pointer points into.
|
||||||
|
/// It is up to the caller to ensure that the returned offset is correct
|
||||||
|
/// in all terms other than alignment.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Accessing adjacent `u8` as `u16`
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(align_offset)]
|
||||||
|
/// # fn foo(n: usize) {
|
||||||
|
/// # use std::mem::align_of;
|
||||||
|
/// # unsafe {
|
||||||
|
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
|
||||||
|
/// let ptr = &x[n] as *const u8;
|
||||||
|
/// let offset = ptr.align_offset(align_of::<u16>());
|
||||||
|
/// if offset < x.len() - n - 1 {
|
||||||
|
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
|
||||||
|
/// assert_ne!(*u16_ptr, 500);
|
||||||
|
/// } else {
|
||||||
|
/// // while the pointer can be aligned via `offset`, it would point
|
||||||
|
/// // outside the allocation
|
||||||
|
/// }
|
||||||
|
/// # } }
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "align_offset", issue = "44488")]
|
||||||
|
pub fn align_offset(self, align: usize) -> usize {
|
||||||
|
unsafe {
|
||||||
|
intrinsics::align_offset(self as *const _, align)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "mut_ptr"]
|
#[lang = "mut_ptr"]
|
||||||
|
@ -1284,6 +1320,43 @@ impl<T: ?Sized> *mut T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the byte offset that needs to be applied in order to
|
||||||
|
/// make the pointer aligned to `align`.
|
||||||
|
/// If it is not possible to align the pointer, the implementation returns
|
||||||
|
/// `usize::max_value()`.
|
||||||
|
///
|
||||||
|
/// There are no guarantees whatsover that offsetting the pointer will not
|
||||||
|
/// overflow or go beyond the allocation that the pointer points into.
|
||||||
|
/// It is up to the caller to ensure that the returned offset is correct
|
||||||
|
/// in all terms other than alignment.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Accessing adjacent `u8` as `u16`
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(align_offset)]
|
||||||
|
/// # fn foo(n: usize) {
|
||||||
|
/// # use std::mem::align_of;
|
||||||
|
/// # unsafe {
|
||||||
|
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
|
||||||
|
/// let ptr = &x[n] as *const u8;
|
||||||
|
/// let offset = ptr.align_offset(align_of::<u16>());
|
||||||
|
/// if offset < x.len() - n - 1 {
|
||||||
|
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
|
||||||
|
/// assert_ne!(*u16_ptr, 500);
|
||||||
|
/// } else {
|
||||||
|
/// // while the pointer can be aligned via `offset`, it would point
|
||||||
|
/// // outside the allocation
|
||||||
|
/// }
|
||||||
|
/// # } }
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "align_offset", issue = "44488")]
|
||||||
|
pub fn align_offset(self, align: usize) -> usize {
|
||||||
|
unsafe {
|
||||||
|
intrinsics::align_offset(self as *const _, align)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
|
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
|
||||||
///
|
///
|
||||||
|
|
|
@ -23,7 +23,6 @@ use fmt;
|
||||||
use iter::{Map, Cloned, FusedIterator};
|
use iter::{Map, Cloned, FusedIterator};
|
||||||
use slice::{self, SliceIndex};
|
use slice::{self, SliceIndex};
|
||||||
use mem;
|
use mem;
|
||||||
use intrinsics::align_offset;
|
|
||||||
|
|
||||||
pub mod pattern;
|
pub mod pattern;
|
||||||
|
|
||||||
|
@ -1515,7 +1514,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
||||||
let ptr = v.as_ptr();
|
let ptr = v.as_ptr();
|
||||||
let align = unsafe {
|
let align = unsafe {
|
||||||
// the offset is safe, because `index` is guaranteed inbounds
|
// the offset is safe, because `index` is guaranteed inbounds
|
||||||
align_offset(ptr.offset(index as isize) as *const (), usize_bytes)
|
ptr.offset(index as isize).align_offset(usize_bytes)
|
||||||
};
|
};
|
||||||
if align == 0 {
|
if align == 0 {
|
||||||
while index < blocks_end {
|
while index < blocks_end {
|
||||||
|
|
|
@ -242,6 +242,7 @@
|
||||||
#![feature(allocator_internals)]
|
#![feature(allocator_internals)]
|
||||||
#![feature(allow_internal_unsafe)]
|
#![feature(allow_internal_unsafe)]
|
||||||
#![feature(allow_internal_unstable)]
|
#![feature(allow_internal_unstable)]
|
||||||
|
#![feature(align_offset)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(cfg_target_has_atomic)]
|
#![feature(cfg_target_has_atomic)]
|
||||||
|
|
|
@ -65,15 +65,12 @@ pub mod fallback {
|
||||||
let usize_bytes = mem::size_of::<usize>();
|
let usize_bytes = mem::size_of::<usize>();
|
||||||
|
|
||||||
// search up to an aligned boundary
|
// search up to an aligned boundary
|
||||||
let align = (ptr as usize) & (usize_bytes- 1);
|
let mut offset = ptr.align_offset(usize_bytes);
|
||||||
let mut offset;
|
if offset > 0 {
|
||||||
if align > 0 {
|
offset = cmp::min(offset, len);
|
||||||
offset = cmp::min(usize_bytes - align, len);
|
|
||||||
if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
|
if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
|
||||||
return Some(index);
|
return Some(index);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// search the body of the text
|
// search the body of the text
|
||||||
|
|
Loading…
Reference in New Issue