Add vectored support to Buf and BufMut

This commit is contained in:
Carl Lerche
2017-03-01 13:18:29 -08:00
parent 4462056e26
commit bb9bf7ee3e
7 changed files with 103 additions and 1 deletions
+1
View File
@@ -21,6 +21,7 @@ categories = ["network-programming", "data-structures"]
[dependencies]
byteorder = "1.0.0"
iovec = { git = "https://github.com/carllerche/iovec" }
[dev-dependencies]
tokio-core = "0.1.0"
+37
View File
@@ -1,5 +1,6 @@
use super::{Take, Reader, Iter, FromBuf};
use byteorder::ByteOrder;
use iovec::IoVec;
use std::{cmp, io, ptr};
@@ -72,6 +73,34 @@ pub trait Buf {
/// ```
fn bytes(&self) -> &[u8];
/// Fills `dst` with potentially multiple slices starting at `self`'s
/// current position.
///
/// If the `Buf` is backed by disjoint slices of bytes, `bytes_vec` enables
/// fetching more than one slice at once. `dst` is a slice of `IoVec`
/// references, enabling the slice to be directly used with [`writev`]
/// without any further conversion. The sum of the lengths of all the
/// buffers in `dst` will be less than or equal to `Buf::remaining()`.
///
/// The entries in `dst` will be overwritten, but the data **contained** by
/// the slices **will not** be modified. If `bytes_vec` does not fill every
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
/// in `self.
///
/// This is a lower level function. Most operations are done with other
/// functions.
///
/// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
if dst.is_empty() {
return 0;
}
dst[0] = self.bytes().into();
1
}
/// Advance the internal cursor of the Buf
///
/// The next call to `bytes` will return a slice starting `cnt` bytes
@@ -576,6 +605,10 @@ impl<'a, T: Buf + ?Sized> Buf for &'a mut T {
(**self).bytes()
}
fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
(**self).bytes_vec(dst)
}
fn advance(&mut self, cnt: usize) {
(**self).advance(cnt)
}
@@ -590,6 +623,10 @@ impl<T: Buf + ?Sized> Buf for Box<T> {
(**self).bytes()
}
fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
(**self).bytes_vec(dst)
}
fn advance(&mut self, cnt: usize) {
(**self).advance(cnt)
}
+38
View File
@@ -1,5 +1,6 @@
use super::{Source, Writer};
use byteorder::ByteOrder;
use iovec::IoVec;
use std::{cmp, io, ptr, usize};
@@ -137,6 +138,35 @@ pub trait BufMut {
/// ```
unsafe fn bytes_mut(&mut self) -> &mut [u8];
/// Fills `dst` with potentially multiple mutable slices starting at `self`'s
/// current position.
///
/// If the `BufMut` is backed by disjoint slices of bytes, `bytes_vec_mut`
/// enables fetching more than one slice at once. `dst` is a slice of
/// mutable `IoVec` references, enabling the slice to be directly used with
/// [`readv`] without any further conversion. The sum of the lengths of all
/// the buffers in `dst` will be less than or equal to
/// `Buf::remaining_mut()`.
///
/// The entries in `dst` will be overwritten, but the data **contained** by
/// the slices **will not** be modified. If `bytes_vec_mut` does not fill every
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
/// in `self.
///
/// This is a lower level function. Most operations are done with other
/// functions.
///
/// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
if dst.is_empty() {
return 0;
}
dst[0] = self.bytes_mut().into();
1
}
/// Transfer bytes into `self` from `src` and advance the cursor by the
/// number of bytes written.
///
@@ -513,6 +543,10 @@ impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
(**self).bytes_mut()
}
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
}
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt)
}
@@ -527,6 +561,10 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
(**self).bytes_mut()
}
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
}
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt)
}
+2 -1
View File
@@ -1229,7 +1229,8 @@ impl<'a> From<&'a [u8]> for BytesMut {
}
} else {
let mut buf = BytesMut::with_capacity(src.len());
buf.put(src.as_ref());
let src: &[u8] = src.as_ref();
buf.put(src);
buf
}
}
+1
View File
@@ -72,6 +72,7 @@
#![doc(html_root_url = "https://docs.rs/bytes/0.4")]
extern crate byteorder;
extern crate iovec;
pub mod buf;
pub use buf::{
+10
View File
@@ -1,7 +1,9 @@
extern crate bytes;
extern crate byteorder;
extern crate iovec;
use bytes::Buf;
use iovec::IoVec;
use std::io::Cursor;
#[test]
@@ -46,3 +48,11 @@ fn test_get_u16_buffer_underflow() {
let mut buf = Cursor::new(b"\x21");
buf.get_u16::<byteorder::BigEndian>();
}
#[test]
fn test_bufs_vec() {
let buf = Cursor::new(b"hello world");
let mut dst: [&IoVec; 2] = Default::default();
assert_eq!(1, buf.bytes_vec(&mut dst[..]));
}
+14
View File
@@ -1,7 +1,9 @@
extern crate bytes;
extern crate byteorder;
extern crate iovec;
use bytes::{BufMut, BytesMut};
use iovec::IoVec;
use std::usize;
use std::fmt::Write;
@@ -56,3 +58,15 @@ fn test_clone() {
buf.write_str(" of our emergecy broadcast system").unwrap();
assert!(buf != buf2);
}
#[test]
fn test_bufs_vec_mut() {
use std::mem;
let mut buf = BytesMut::from(&b"hello world"[..]);
unsafe {
let mut dst: [&mut IoVec; 2] = mem::zeroed();
assert_eq!(1, buf.bytes_vec_mut(&mut dst[..]));
}
}