diff options
| author | Mathieu David <mathieudavid@mathieudavid.org> | 2015-07-27 20:46:01 +0200 |
|---|---|---|
| committer | Mathieu David <mathieudavid@mathieudavid.org> | 2015-07-27 20:46:01 +0200 |
| commit | f6e9240a99e86d2c799dc29f179dd2870e51f71d (patch) | |
| tree | a7e5ba20745b16949a45a4612b2708e262693a7b /src/libstd/sys/common | |
| parent | 003c3eaa62981b791f9eb7bcad015baa1e00d98c (diff) | |
| parent | 3351afeecffcc9ebaeb1188a5cde976da8e4a5aa (diff) | |
| download | rust-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.rs | 139 | ||||
| -rw-r--r-- | src/libstd/sys/common/mod.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/common/net.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys/common/stack.rs | 18 | ||||
| -rw-r--r-- | src/libstd/sys/common/thread_info.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys/common/wtf8.rs | 31 |
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 |
