diff options
Diffstat (limited to 'third_party/rust/iovec/src')
-rw-r--r-- | third_party/rust/iovec/src/lib.rs | 161 | ||||
-rw-r--r-- | third_party/rust/iovec/src/sys/mod.rs | 26 | ||||
-rw-r--r-- | third_party/rust/iovec/src/sys/unix.rs | 52 | ||||
-rw-r--r-- | third_party/rust/iovec/src/sys/unknown.rs | 57 | ||||
-rw-r--r-- | third_party/rust/iovec/src/sys/windows.rs | 68 | ||||
-rw-r--r-- | third_party/rust/iovec/src/unix.rs | 68 | ||||
-rw-r--r-- | third_party/rust/iovec/src/windows.rs | 0 |
7 files changed, 432 insertions, 0 deletions
diff --git a/third_party/rust/iovec/src/lib.rs b/third_party/rust/iovec/src/lib.rs new file mode 100644 index 0000000000..1e091a46c9 --- /dev/null +++ b/third_party/rust/iovec/src/lib.rs @@ -0,0 +1,161 @@ +//! A specialized byte slice type for performing vectored I/O operations. +//! +//! For more detail, see [`IoVec`] documentation. +//! +//! [`IoVec`]: struct.IoVec.html + +#[cfg(unix)] +extern crate libc; + +mod sys; + +use std::{ops, mem}; + +#[cfg(unix)] +pub mod unix; + +/// Max length of an `IoVec` slice. +/// +/// Attempts to convert slices longer than this value will result in a panic. +pub const MAX_LENGTH: usize = sys::MAX_LENGTH; + +/// A specialized byte slice type for performing vectored I/O operations. +/// +/// On all systems, the types needed to perform vectored I/O systems have the +/// same size as Rust's [`slice`]. However, the layout is not necessarily the +/// same. `IoVec` provides a portable compatibility layer. +/// +/// The `IoVec` behaves like a Rust [`slice`], providing the same functions. +/// It also provides conversion functions to and from the OS specific vectored +/// types. +/// +/// [`slice`]: https://doc.rust-lang.org/std/primitive.slice.html +/// +/// # Examples +/// +/// ``` +/// use iovec::IoVec; +/// +/// let mut data = vec![]; +/// data.extend_from_slice(b"hello"); +/// +/// let iovec: &IoVec = data.as_slice().into(); +/// +/// assert_eq!(&iovec[..], &b"hello"[..]); +/// ``` +/// +/// # Panics +/// +/// Attempting to convert a zero-length slice or a slice longer than +/// [`MAX_LENGTH`] to an `IoVec` will result in a panic. +/// +/// [`MAX_LENGTH`]: constant.MAX_LENGTH.html +pub struct IoVec { + sys: sys::IoVec, +} + +impl IoVec { + pub fn from_bytes(slice: &[u8]) -> Option<&IoVec> { + if slice.len() == 0 { + return None + } + unsafe { + let iovec: &sys::IoVec = slice.into(); + Some(mem::transmute(iovec)) + } + } + + pub fn from_bytes_mut(slice: &mut [u8]) -> Option<&mut IoVec> { + if slice.len() == 0 { + return None + } + unsafe { + let iovec: &mut sys::IoVec = slice.into(); + Some(mem::transmute(iovec)) + } + } + + #[deprecated(since = "0.1.0", note = "deref instead")] + #[doc(hidden)] + pub fn as_bytes(&self) -> &[u8] { + &**self + } + + #[deprecated(since = "0.1.0", note = "deref instead")] + #[doc(hidden)] + pub fn as_mut_bytes(&mut self) -> &mut [u8] { + &mut **self + } +} + +impl ops::Deref for IoVec { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.sys.as_ref() + } +} + +impl ops::DerefMut for IoVec { + fn deref_mut(&mut self) -> &mut [u8] { + self.sys.as_mut() + } +} + +#[doc(hidden)] +impl<'a> From<&'a [u8]> for &'a IoVec { + fn from(bytes: &'a [u8]) -> &'a IoVec { + IoVec::from_bytes(bytes) + .expect("this crate accidentally accepted 0-sized slices \ + originally but this was since discovered as a soundness \ + hole, it's recommended to use the `from_bytes` \ + function instead") + } +} + +#[doc(hidden)] +impl<'a> From<&'a mut [u8]> for &'a mut IoVec { + fn from(bytes: &'a mut [u8]) -> &'a mut IoVec { + IoVec::from_bytes_mut(bytes) + .expect("this crate accidentally accepted 0-sized slices \ + originally but this was since discovered as a soundness \ + hole, it's recommended to use the `from_bytes_mut` \ + function instead") + } +} + +#[doc(hidden)] +impl<'a> Default for &'a IoVec { + fn default() -> Self { + panic!("this implementation was accidentally provided but is \ + unfortunately unsound, it's recommended to stop using \ + `IoVec::default` or construct a vector with a nonzero length"); + } +} + +#[doc(hidden)] +impl<'a> Default for &'a mut IoVec { + fn default() -> Self { + panic!("this implementation was accidentally provided but is \ + unfortunately unsound, it's recommended to stop using \ + `IoVec::default` or construct a vector with a nonzero length"); + } +} + +#[cfg(test)] +mod test { + use super::IoVec; + + #[test] + fn convert_ref() { + let buf: &IoVec = (&b"hello world"[..]).into(); + assert_eq!(buf[..], b"hello world"[..]); + } + + #[test] + fn convert_mut() { + let mut buf: Vec<u8> = b"hello world".to_vec(); + let buf: &mut IoVec = (&mut buf[..]).into(); + assert_eq!(buf[..], b"hello world"[..]); + } +} diff --git a/third_party/rust/iovec/src/sys/mod.rs b/third_party/rust/iovec/src/sys/mod.rs new file mode 100644 index 0000000000..3e0efc99e8 --- /dev/null +++ b/third_party/rust/iovec/src/sys/mod.rs @@ -0,0 +1,26 @@ +#[cfg(unix)] +mod unix; + +#[cfg(unix)] +pub use self::unix::{ + IoVec, + MAX_LENGTH, +}; + +#[cfg(windows)] +mod windows; + +#[cfg(windows)] +pub use self::windows::{ + IoVec, + MAX_LENGTH, +}; + +#[cfg(not(any(windows, unix)))] +mod unknown; + +#[cfg(not(any(windows, unix)))] +pub use self::unknown::{ + IoVec, + MAX_LENGTH, +}; diff --git a/third_party/rust/iovec/src/sys/unix.rs b/third_party/rust/iovec/src/sys/unix.rs new file mode 100644 index 0000000000..4dbc0674f8 --- /dev/null +++ b/third_party/rust/iovec/src/sys/unix.rs @@ -0,0 +1,52 @@ +use libc; +use std::{mem, slice, usize}; + +pub struct IoVec { + inner: [u8], +} + +pub const MAX_LENGTH: usize = usize::MAX; + +impl IoVec { + pub fn as_ref(&self) -> &[u8] { + unsafe { + let vec = self.iovec(); + slice::from_raw_parts(vec.iov_base as *const u8, vec.iov_len) + } + } + + pub fn as_mut(&mut self) -> &mut [u8] { + unsafe { + let vec = self.iovec(); + slice::from_raw_parts_mut(vec.iov_base as *mut u8, vec.iov_len) + } + } + + unsafe fn iovec(&self) -> libc::iovec { + mem::transmute(&self.inner) + } +} + +impl<'a> From<&'a [u8]> for &'a IoVec { + fn from(src: &'a [u8]) -> Self { + assert!(src.len() > 0); + unsafe { + mem::transmute(libc::iovec { + iov_base: src.as_ptr() as *mut _, + iov_len: src.len(), + }) + } + } +} + +impl<'a> From<&'a mut [u8]> for &'a mut IoVec { + fn from(src: &'a mut [u8]) -> Self { + assert!(src.len() > 0); + unsafe { + mem::transmute(libc::iovec { + iov_base: src.as_ptr() as *mut _, + iov_len: src.len(), + }) + } + } +} diff --git a/third_party/rust/iovec/src/sys/unknown.rs b/third_party/rust/iovec/src/sys/unknown.rs new file mode 100644 index 0000000000..37acedd78b --- /dev/null +++ b/third_party/rust/iovec/src/sys/unknown.rs @@ -0,0 +1,57 @@ +use std::{mem, slice, usize}; + +#[derive(Clone)] +pub struct WasmIoVec { + ptr: *const u8, + len: usize, +} + +pub struct IoVec { + inner: [u8], +} + +pub const MAX_LENGTH: usize = usize::MAX; + +impl IoVec { + pub fn as_ref(&self) -> &[u8] { + unsafe { + let vec = self.iovec(); + slice::from_raw_parts(vec.ptr as *const u8, vec.len) + } + } + + pub fn as_mut(&mut self) -> &mut [u8] { + unsafe { + let vec = self.iovec(); + slice::from_raw_parts_mut(vec.ptr as *mut u8, vec.len) + } + } + + unsafe fn iovec(&self) -> WasmIoVec { + mem::transmute(&self.inner) + } +} + +impl<'a> From<&'a [u8]> for &'a IoVec { + fn from(src: &'a [u8]) -> Self { + assert!(src.len() > 0); + unsafe { + mem::transmute(WasmIoVec { + ptr: src.as_ptr() as *mut _, + len: src.len(), + }) + } + } +} + +impl<'a> From<&'a mut [u8]> for &'a mut IoVec { + fn from(src: &'a mut [u8]) -> Self { + assert!(src.len() > 0); + unsafe { + mem::transmute(WasmIoVec { + ptr: src.as_ptr() as *mut _, + len: src.len(), + }) + } + } +} diff --git a/third_party/rust/iovec/src/sys/windows.rs b/third_party/rust/iovec/src/sys/windows.rs new file mode 100644 index 0000000000..fc5b8fb427 --- /dev/null +++ b/third_party/rust/iovec/src/sys/windows.rs @@ -0,0 +1,68 @@ +use std::{mem, slice, u32}; + +// declare the types we need directly here to avoid bringing +// in the old and slow winapi 0.2 dependency. + +type DWORD = u32; +type ULONG = u32; +type CHAR = i8; + +#[repr(C)] +struct WSABUF { + pub len: ULONG, + pub buf: *mut CHAR, +} + +pub struct IoVec { + inner: [u8], +} + +pub const MAX_LENGTH: usize = u32::MAX as usize; + +impl IoVec { + pub fn as_ref(&self) -> &[u8] { + unsafe { + let vec = self.wsabuf(); + slice::from_raw_parts(vec.buf as *const u8, vec.len as usize) + } + } + + pub fn as_mut(&mut self) -> &mut [u8] { + unsafe { + let vec = self.wsabuf(); + slice::from_raw_parts_mut(vec.buf as *mut u8, vec.len as usize) + } + } + + unsafe fn wsabuf(&self) -> WSABUF { + mem::transmute(&self.inner) + } +} + +impl<'a> From<&'a [u8]> for &'a IoVec { + fn from(src: &'a [u8]) -> Self { + assert!(src.len() > 0); + assert!(src.len() <= MAX_LENGTH); + + unsafe { + mem::transmute(WSABUF { + buf: src.as_ptr() as *mut _, + len: src.len() as DWORD, + }) + } + } +} + +impl<'a> From<&'a mut [u8]> for &'a mut IoVec { + fn from(src: &'a mut [u8]) -> Self { + assert!(src.len() > 0); + assert!(src.len() <= MAX_LENGTH); + + unsafe { + mem::transmute(WSABUF { + buf: src.as_ptr() as *mut _, + len: src.len() as DWORD, + }) + } + } +} diff --git a/third_party/rust/iovec/src/unix.rs b/third_party/rust/iovec/src/unix.rs new file mode 100644 index 0000000000..3ef3728bb0 --- /dev/null +++ b/third_party/rust/iovec/src/unix.rs @@ -0,0 +1,68 @@ +//! IoVec extensions for Unix platforms. +//! +//! These functions provide conversions to unix specific representations of the +//! vectored data. +//! +//! # Examples +//! +//! ``` +//! use iovec::IoVec; +//! use iovec::unix; +//! +//! let a = b"hello".to_vec(); +//! let b = b"world".to_vec(); +//! +//! let bufs: &[&IoVec] = &[(&a[..]).into(), (&b[..]).into()]; +//! let os_bufs = unix::as_os_slice(&bufs[..]); +//! +//! // Use the `os_bufs` slice with `writev`. +//! ``` + +use IoVec; +use libc; + +use std::mem; + +/// Convert a slice of `IoVec` refs to a slice of `libc::iovec`. +/// +/// The return value can be passed to `writev` bindings. +/// +/// # Examples +/// +/// ``` +/// use iovec::IoVec; +/// use iovec::unix; +/// +/// let a = b"hello".to_vec(); +/// let b = b"world".to_vec(); +/// +/// let bufs: &[&IoVec] = &[a[..].into(), b[..].into()]; +/// let os_bufs = unix::as_os_slice(bufs); +/// +/// // Use the `os_bufs` slice with `writev`. +/// ``` +pub fn as_os_slice<'a>(iov: &'a [&IoVec]) -> &'a [libc::iovec] { + unsafe { mem::transmute(iov) } +} + +/// Convert a mutable slice of `IoVec` refs to a mutable slice of `libc::iovec`. +/// +/// The return value can be passed to `readv` bindings. +/// +/// # Examples +/// +/// ``` +/// use iovec::IoVec; +/// use iovec::unix; +/// +/// let mut a = [0; 10]; +/// let mut b = [0; 10]; +/// +/// let bufs: &mut [&mut IoVec] = &mut [(&mut a[..]).into(), (&mut b[..]).into()]; +/// let os_bufs = unix::as_os_slice_mut(bufs); +/// +/// // Use the `os_bufs` slice with `readv`. +/// ``` +pub fn as_os_slice_mut<'a>(iov: &'a mut [&mut IoVec]) -> &'a mut [libc::iovec] { + unsafe { mem::transmute(iov) } +} diff --git a/third_party/rust/iovec/src/windows.rs b/third_party/rust/iovec/src/windows.rs new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/third_party/rust/iovec/src/windows.rs |