about summary refs log tree commit diff
path: root/src/libstd/sys/common
diff options
context:
space:
mode:
authorMathieu David <mathieudavid@mathieudavid.org>2015-07-27 20:46:01 +0200
committerMathieu David <mathieudavid@mathieudavid.org>2015-07-27 20:46:01 +0200
commitf6e9240a99e86d2c799dc29f179dd2870e51f71d (patch)
treea7e5ba20745b16949a45a4612b2708e262693a7b /src/libstd/sys/common
parent003c3eaa62981b791f9eb7bcad015baa1e00d98c (diff)
parent3351afeecffcc9ebaeb1188a5cde976da8e4a5aa (diff)
downloadrust-f6e9240a99e86d2c799dc29f179dd2870e51f71d.tar.gz
rust-f6e9240a99e86d2c799dc29f179dd2870e51f71d.zip
Fix the relative path issue by including the files using include_bytes!
Diffstat (limited to 'src/libstd/sys/common')
-rw-r--r--src/libstd/sys/common/io.rs139
-rw-r--r--src/libstd/sys/common/mod.rs1
-rw-r--r--src/libstd/sys/common/net.rs6
-rw-r--r--src/libstd/sys/common/stack.rs18
-rw-r--r--src/libstd/sys/common/thread_info.rs8
-rw-r--r--src/libstd/sys/common/wtf8.rs31
6 files changed, 180 insertions, 23 deletions
diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs
new file mode 100644
index 00000000000..151d853fc9f
--- /dev/null
+++ b/src/libstd/sys/common/io.rs
@@ -0,0 +1,139 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use prelude::v1::*;
+use io;
+use io::ErrorKind;
+use io::Read;
+use slice::from_raw_parts_mut;
+
+// Provides read_to_end functionality over an uninitialized buffer.
+// This function is unsafe because it calls the underlying
+// read function with a slice into uninitialized memory. The default
+// implementation of read_to_end for readers will zero out new memory in
+// the buf before passing it to read, but avoiding this zero can often
+// lead to a fairly significant performance win.
+//
+// Implementations using this method have to adhere to two guarantees:
+//  *  The implementation of read never reads the buffer provided.
+//  *  The implementation of read correctly reports how many bytes were written.
+pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::Result<usize> {
+
+    let start_len = buf.len();
+    buf.reserve(16);
+
+    // Always try to read into the empty space of the vector (from the length to the capacity).
+    // If the vector ever fills up then we reserve an extra byte which should trigger the normal
+    // reallocation routines for the vector, which will likely double the size.
+    //
+    // This function is similar to the read_to_end function in std::io, but the logic about
+    // reservations and slicing is different enough that this is duplicated here.
+    loop {
+        if buf.len() == buf.capacity() {
+            buf.reserve(1);
+        }
+
+        let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize),
+                                           buf.capacity() - buf.len());
+
+        match r.read(buf_slice) {
+            Ok(0) => { return Ok(buf.len() - start_len); }
+            Ok(n) => { let len = buf.len() + n; buf.set_len(len); },
+            Err(ref e) if e.kind() == ErrorKind::Interrupted => { }
+            Err(e) => { return Err(e); }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::v1::*;
+    use io::prelude::*;
+    use super::*;
+    use io;
+    use io::{ErrorKind, Take, Repeat, repeat};
+    use test;
+    use slice::from_raw_parts;
+
+    struct ErrorRepeat {
+        lr: Take<Repeat>
+    }
+
+    fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat {
+        ErrorRepeat { lr: repeat(byte).take(limit) }
+    }
+
+    impl Read for ErrorRepeat {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            let ret = self.lr.read(buf);
+            if let Ok(0) = ret {
+                return Err(io::Error::new(ErrorKind::Other, ""))
+            }
+            ret
+        }
+    }
+
+    fn init_vec_data() -> Vec<u8> {
+        let mut vec = vec![10u8; 200];
+        unsafe { vec.set_len(0); }
+        vec
+    }
+
+    fn assert_all_eq(buf: &[u8], value: u8) {
+        for n in buf {
+            assert_eq!(*n, value);
+        }
+    }
+
+    fn validate(buf: &Vec<u8>, good_read_len: usize) {
+        assert_all_eq(buf, 1u8);
+        let cap = buf.capacity();
+        let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize),
+                                                    cap - good_read_len) };
+        assert_all_eq(end_slice, 10u8);
+    }
+
+    #[test]
+    fn read_to_end_uninit_error() {
+        let mut er = error_repeat(1,100);
+        let mut vec = init_vec_data();
+        if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } {
+            validate(&vec, 100);
+        } else {
+            assert!(false);
+        }
+    }
+
+    #[test]
+    fn read_to_end_uninit_zero_len_vec() {
+        let mut er = repeat(1).take(100);
+        let mut vec = Vec::new();
+        let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() };
+        assert_all_eq(&vec, 1u8);
+        assert_eq!(vec.len(), n);
+    }
+
+    #[test]
+    fn read_to_end_uninit_good() {
+        let mut er = repeat(1).take(100);
+        let mut vec = init_vec_data();
+        let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() };
+        validate(&vec, 100);
+        assert_eq!(vec.len(), n);
+    }
+
+    #[bench]
+    fn bench_uninitialized(b: &mut test::Bencher) {
+        b.iter(|| {
+            let mut lr = repeat(1).take(10000000);
+            let mut vec = Vec::with_capacity(1024);
+            unsafe { read_to_end_uninitialized(&mut lr, &mut vec) };
+        });
+    }
+}
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index b528575bbed..69c54f98917 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -16,6 +16,7 @@ pub mod backtrace;
 pub mod condvar;
 pub mod mutex;
 pub mod net;
+pub mod io;
 pub mod poison;
 pub mod remutex;
 pub mod rwlock;
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 5890e6a7889..6dd222b8f6e 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -184,6 +184,8 @@ impl TcpStream {
 
     pub fn socket(&self) -> &Socket { &self.inner }
 
+    pub fn into_socket(self) -> Socket { self.inner }
+
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         setsockopt(&self.inner, libc::IPPROTO_TCP, libc::TCP_NODELAY,
                    nodelay as c_int)
@@ -336,6 +338,8 @@ impl TcpListener {
 
     pub fn socket(&self) -> &Socket { &self.inner }
 
+    pub fn into_socket(self) -> Socket { self.inner }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         sockname(|buf, len| unsafe {
             libc::getsockname(*self.inner.as_inner(), buf, len)
@@ -396,6 +400,8 @@ impl UdpSocket {
 
     pub fn socket(&self) -> &Socket { &self.inner }
 
+    pub fn into_socket(self) -> Socket { self.inner }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         sockname(|buf, len| unsafe {
             libc::getsockname(*self.inner.as_inner(), buf, len)
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
index 11982ebc572..41c8ac4aed3 100644
--- a/src/libstd/sys/common/stack.rs
+++ b/src/libstd/sys/common/stack.rs
@@ -170,8 +170,7 @@ pub unsafe fn record_sp_limit(limit: usize) {
         asm!("movl $$0x48+90*4, %eax
               movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
     }
-    #[cfg(all(target_arch = "x86",
-              any(target_os = "linux", target_os = "freebsd")))]
+    #[cfg(all(target_arch = "x86", target_os = "linux"))]
     #[inline(always)]
     unsafe fn target_record_sp_limit(limit: usize) {
         asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
@@ -197,11 +196,14 @@ pub unsafe fn record_sp_limit(limit: usize) {
     // aarch64 - FIXME(AARCH64): missing...
     // powerpc - FIXME(POWERPC): missing...
     // arm-ios - iOS segmented stack is disabled for now, see related notes
-    // openbsd - segmented stack is disabled
+    // openbsd/bitrig/netbsd - no segmented stacks.
+    // x86-freebsd - no segmented stacks.
     #[cfg(any(target_arch = "aarch64",
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
+              all(target_arch = "x86", target_os = "freebsd"),
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     unsafe fn target_record_sp_limit(_: usize) {
     }
@@ -261,8 +263,7 @@ pub unsafe fn get_sp_limit() -> usize {
               movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
         return limit;
     }
-    #[cfg(all(target_arch = "x86",
-              any(target_os = "linux", target_os = "freebsd")))]
+    #[cfg(all(target_arch = "x86", target_os = "linux"))]
     #[inline(always)]
     unsafe fn target_get_sp_limit() -> usize {
         let limit;
@@ -290,15 +291,18 @@ pub unsafe fn get_sp_limit() -> usize {
 
     // aarch64 - FIXME(AARCH64): missing...
     // powerpc - FIXME(POWERPC): missing...
-    // arm-ios - iOS doesn't support segmented stacks yet.
-    // openbsd - OpenBSD doesn't support segmented stacks.
+    // arm-ios - no segmented stacks.
+    // openbsd/bitrig/netbsd - no segmented stacks.
+    // x86-freebsd - no segmented stacks..
     //
     // This function might be called by runtime though
     // so it is unsafe to unreachable, let's return a fixed constant.
     #[cfg(any(target_arch = "aarch64",
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
+              all(target_arch = "x86", target_os = "freebsd"),
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     #[inline(always)]
     unsafe fn target_get_sp_limit() -> usize {
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index ae55bae37aa..bb47c946e49 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -18,7 +18,7 @@ use thread::Thread;
 use thread::LocalKeyState;
 
 struct ThreadInfo {
-    stack_guard: usize,
+    stack_guard: Option<usize>,
     thread: Thread,
 }
 
@@ -33,7 +33,7 @@ impl ThreadInfo {
         THREAD_INFO.with(move |c| {
             if c.borrow().is_none() {
                 *c.borrow_mut() = Some(ThreadInfo {
-                    stack_guard: 0,
+                    stack_guard: None,
                     thread: NewThread::new(None),
                 })
             }
@@ -47,10 +47,10 @@ pub fn current_thread() -> Option<Thread> {
 }
 
 pub fn stack_guard() -> Option<usize> {
-    ThreadInfo::with(|info| info.stack_guard)
+    ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
 }
 
-pub fn set(stack_guard: usize, thread: Thread) {
+pub fn set(stack_guard: Option<usize>, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
         stack_guard: stack_guard,
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index 8ea673d2162..6f15d606724 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -32,17 +32,18 @@ use core::str::next_code_point;
 
 use ascii::*;
 use borrow::Cow;
+use char;
 use cmp;
 use fmt;
 use hash::{Hash, Hasher};
 use iter::FromIterator;
 use mem;
 use ops;
+use rustc_unicode::str::{Utf16Item, utf16_items};
 use slice;
 use str;
 use string::String;
 use sys_common::AsInner;
-use rustc_unicode::str::{Utf16Item, utf16_items};
 use vec::Vec;
 
 const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD";
@@ -107,7 +108,7 @@ impl CodePoint {
     pub fn to_char(&self) -> Option<char> {
         match self.value {
             0xD800 ... 0xDFFF => None,
-            _ => Some(unsafe { mem::transmute(self.value) })
+            _ => Some(unsafe { char::from_u32_unchecked(self.value) })
         }
     }
 
@@ -213,18 +214,16 @@ impl Wtf8Buf {
             // Attempt to not use an intermediate buffer by just pushing bytes
             // directly onto this string.
             let slice = slice::from_raw_parts_mut(
-                self.bytes.as_mut_ptr().offset(cur_len as isize),
-                4
+                self.bytes.as_mut_ptr().offset(cur_len as isize), 4
             );
-            let used = encode_utf8_raw(code_point.value, mem::transmute(slice))
-                .unwrap_or(0);
+            let used = encode_utf8_raw(code_point.value, slice).unwrap();
             self.bytes.set_len(cur_len + used);
         }
     }
 
     #[inline]
     pub fn as_slice(&self) -> &Wtf8 {
-        unsafe { mem::transmute(&*self.bytes) }
+        unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
     }
 
     /// Reserves capacity for at least `additional` more bytes to be inserted
@@ -457,7 +456,16 @@ impl Wtf8 {
     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
     #[inline]
     pub fn from_str(value: &str) -> &Wtf8 {
-        unsafe { mem::transmute(value.as_bytes()) }
+        unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
+    }
+
+    /// Creates a WTF-8 slice from a WTF-8 byte slice.
+    ///
+    /// Since the byte slice is not checked for valid WTF-8, this functions is
+    /// marked unsafe.
+    #[inline]
+    unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
+        mem::transmute(value)
     }
 
     /// Returns the length, in WTF-8 bytes.
@@ -682,7 +690,7 @@ fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
 #[inline]
 fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
     let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
-    unsafe { mem::transmute(code_point) }
+    unsafe { char::from_u32_unchecked(code_point) }
 }
 
 /// Copied from core::str::StrPrelude::is_char_boundary
@@ -699,7 +707,7 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
 #[inline]
 pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
     // memory layout of an &[u8] and &Wtf8 are the same
-    mem::transmute(slice::from_raw_parts(
+    Wtf8::from_bytes_unchecked(slice::from_raw_parts(
         s.bytes.as_ptr().offset(begin as isize),
         end - begin
     ))
@@ -821,7 +829,6 @@ mod tests {
     use prelude::v1::*;
     use borrow::Cow;
     use super::*;
-    use mem::transmute;
 
     #[test]
     fn code_point_from_u32() {
@@ -962,7 +969,7 @@ mod tests {
         string.push_wtf8(Wtf8::from_str(" 💩"));
         assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
 
-        fn w(value: &[u8]) -> &Wtf8 { unsafe { transmute(value) } }
+        fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } }
 
         let mut string = Wtf8Buf::new();
         string.push_wtf8(w(b"\xED\xA0\xBD"));  // lead