about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-07-26 18:29:38 +0200
committerRalf Jung <post@ralfj.de>2018-07-26 18:29:38 +0200
commit70cb75c31e5d084da3a06457484096330ca72a61 (patch)
tree1897321a88e38e0243e4af552b64e5b0cb682a41
parent0fc4501256b002aef627880a9f6d18065b0ca931 (diff)
downloadrust-70cb75c31e5d084da3a06457484096330ca72a61.tar.gz
rust-70cb75c31e5d084da3a06457484096330ca72a61.zip
make memrchr use align_offset
-rw-r--r--src/libcore/slice/memchr.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs
index 7b62e7b0620..dbbe1c07c23 100644
--- a/src/libcore/slice/memchr.rs
+++ b/src/libcore/slice/memchr.rs
@@ -102,8 +102,24 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     let ptr = text.as_ptr();
     let usize_bytes = mem::size_of::<usize>();
 
+    // a version of align_offset that says how much must be *subtracted*
+    // from a pointer to be aligned.
+    #[inline(always)]
+    fn align_offset_down(ptr: *const u8, align: usize) -> usize {
+        let align_offset = ptr.align_offset(align);
+        if align_offset > align {
+            // Not possible to align
+            usize::max_value()
+        } else if align_offset == 0 {
+            0
+        } else {
+            // E.g. if align=8 and we have to add 1, then we can also subtract 7.
+            align - align_offset
+        }
+    }
+
     // search to an aligned boundary
-    let end_align = (ptr as usize + len) & (usize_bytes - 1);
+    let end_align = align_offset_down(unsafe { ptr.offset(len as isize) }, usize_bytes);
     let mut offset;
     if end_align > 0 {
         offset = if end_align >= len { 0 } else { len - end_align };