diff options
Diffstat (limited to 'src/sys/uio.rs')
-rw-r--r-- | src/sys/uio.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/sys/uio.rs b/src/sys/uio.rs new file mode 100644 index 00000000..322182c5 --- /dev/null +++ b/src/sys/uio.rs @@ -0,0 +1,78 @@ + +mod ffi { + use super::IoVec; + use libc::{ssize_t]; + + // vectorized version of write + // doc: http://man7.org/linux/man-pages/man2/writev.2.html + pub fn writev(fd: Fd, iov: *const IoVec<&[u8]>, iovcnt: c_int) -> ssize_t; + + // vectorized version of read + // doc: http://man7.org/linux/man-pages/man2/readv.2.html + pub fn readv(fd: Fd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t; +} + +pub fn writev(fd: Fd, iov: &[IoVec<&[u8]>]) -> NixResult<usize> { + let res = unsafe { ffi::writev(fd, iov.as_ptr(), iov.len() as c_int) }; + + if res < 0 { + return Err(NixError::Sys(Errno::last())); + } + + return Ok(res as usize) +} + +pub fn readv(fd: Fd, iov: &mut [IoVec<&mut [u8]>]) -> NixResult<usize> { + let res = unsafe { ffi::readv(fd, iov.as_ptr(), iov.len() as c_int) }; + if res < 0 { + return Err(NixError::Sys(Errno::last())); + } + + return Ok(res as usize) +} + +#[repr(C)] +pub struct IoVec<T> { + iov_base: *mut c_void, + iov_len: size_t, + phantom: PhantomData<T> +} + +impl<T> IoVec<T> { + #[inline] + pub fn as_slice<'a>(&'a self) -> &'a [u8] { + use std::slice; + + unsafe { + slice::from_raw_parts( + self.iov_base as *const u8, + self.iov_len as usize) + } + } +} + +impl<'a> IoVec<&'a [u8]> { + pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> { + IoVec { + iov_base: buf.as_ptr() as *mut c_void, + iov_len: buf.len() as size_t, + phantom: PhantomData + } + } +} + +impl<'a> IoVec<&'a mut [u8]> { + pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> { + IoVec { + iov_base: buf.as_ptr() as *mut c_void, + iov_len: buf.len() as size_t, + phantom: PhantomData + } + } +} + +#[test] +pub fn test_size_of_io_vec() { + use nixtest; + nixtest::assert_size_of::<IoVec<&[u8]>>("iovec"); +} |