aboutsummaryrefslogtreecommitdiff
path: root/src/buf/buf_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/buf/buf_impl.rs')
-rw-r--r--src/buf/buf_impl.rs184
1 files changed, 124 insertions, 60 deletions
diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs
index 5cd7c68..16ad8a7 100644
--- a/src/buf/buf_impl.rs
+++ b/src/buf/buf_impl.rs
@@ -1,3 +1,7 @@
+#[cfg(feature = "std")]
+use crate::buf::{reader, Reader};
+use crate::buf::{take, Chain, Take};
+
use core::{cmp, mem, ptr};
#[cfg(feature = "std")]
@@ -12,7 +16,7 @@ macro_rules! buf_get_impl {
// this Option<ret> trick is to avoid keeping a borrow on self
// when advance() is called (mut borrow) and to call bytes() only once
let ret = $this
- .bytes()
+ .chunk()
.get(..SIZE)
.map(|src| unsafe { $typ::$conv(*(src as *const _ as *const [_; SIZE])) });
@@ -74,7 +78,7 @@ pub trait Buf {
/// the buffer.
///
/// This value is greater than or equal to the length of the slice returned
- /// by `bytes`.
+ /// by `chunk()`.
///
/// # Examples
///
@@ -111,31 +115,31 @@ pub trait Buf {
///
/// let mut buf = &b"hello world"[..];
///
- /// assert_eq!(buf.bytes(), &b"hello world"[..]);
+ /// assert_eq!(buf.chunk(), &b"hello world"[..]);
///
/// buf.advance(6);
///
- /// assert_eq!(buf.bytes(), &b"world"[..]);
+ /// assert_eq!(buf.chunk(), &b"world"[..]);
/// ```
///
/// # Implementer notes
///
/// This function should never panic. Once the end of the buffer is reached,
- /// i.e., `Buf::remaining` returns 0, calls to `bytes` should return an
+ /// i.e., `Buf::remaining` returns 0, calls to `chunk()` should return an
/// empty slice.
- fn bytes(&self) -> &[u8];
+ fn chunk(&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_vectored` enables
+ /// If the `Buf` is backed by disjoint slices of bytes, `chunk_vectored` enables
/// fetching more than one slice at once. `dst` is a slice of `IoSlice`
/// 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_vectored` does not fill every
+ /// the slices **will not** be modified. If `chunk_vectored` does not fill every
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
/// in `self.
///
@@ -145,7 +149,7 @@ pub trait Buf {
/// # Implementer notes
///
/// This function should never panic. Once the end of the buffer is reached,
- /// i.e., `Buf::remaining` returns 0, calls to `bytes_vectored` must return 0
+ /// i.e., `Buf::remaining` returns 0, calls to `chunk_vectored` must return 0
/// without mutating `dst`.
///
/// Implementations should also take care to properly handle being called
@@ -153,13 +157,13 @@ pub trait Buf {
///
/// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html
#[cfg(feature = "std")]
- fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
+ fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
if dst.is_empty() {
return 0;
}
if self.has_remaining() {
- dst[0] = IoSlice::new(self.bytes());
+ dst[0] = IoSlice::new(self.chunk());
1
} else {
0
@@ -168,7 +172,7 @@ pub trait Buf {
/// Advance the internal cursor of the Buf
///
- /// The next call to `bytes` will return a slice starting `cnt` bytes
+ /// The next call to `chunk()` will return a slice starting `cnt` bytes
/// further into the underlying buffer.
///
/// # Examples
@@ -178,11 +182,11 @@ pub trait Buf {
///
/// let mut buf = &b"hello world"[..];
///
- /// assert_eq!(buf.bytes(), &b"hello world"[..]);
+ /// assert_eq!(buf.chunk(), &b"hello world"[..]);
///
/// buf.advance(6);
///
- /// assert_eq!(buf.bytes(), &b"world"[..]);
+ /// assert_eq!(buf.chunk(), &b"world"[..]);
/// ```
///
/// # Panics
@@ -249,7 +253,7 @@ pub trait Buf {
let cnt;
unsafe {
- let src = self.bytes();
+ let src = self.chunk();
cnt = cmp::min(src.len(), dst.len() - off);
ptr::copy_nonoverlapping(src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
@@ -279,7 +283,7 @@ pub trait Buf {
/// This function panics if there is no more remaining data in `self`.
fn get_u8(&mut self) -> u8 {
assert!(self.remaining() >= 1);
- let ret = self.bytes()[0];
+ let ret = self.chunk()[0];
self.advance(1);
ret
}
@@ -302,7 +306,7 @@ pub trait Buf {
/// This function panics if there is no more remaining data in `self`.
fn get_i8(&mut self) -> i8 {
assert!(self.remaining() >= 1);
- let ret = self.bytes()[0] as i8;
+ let ret = self.chunk()[0] as i8;
self.advance(1);
ret
}
@@ -791,22 +795,111 @@ pub trait Buf {
f64::from_bits(Self::get_u64_le(self))
}
- /// Consumes remaining bytes inside self and returns new instance of `Bytes`
+ /// Consumes `len` bytes inside self and returns new instance of `Bytes`
+ /// with this data.
+ ///
+ /// This function may be optimized by the underlying type to avoid actual
+ /// copies. For example, `Bytes` implementation will do a shallow copy
+ /// (ref-count increment).
///
/// # Examples
///
/// ```
/// use bytes::Buf;
///
- /// let bytes = (&b"hello world"[..]).to_bytes();
- /// assert_eq!(&bytes[..], &b"hello world"[..]);
+ /// let bytes = (&b"hello world"[..]).copy_to_bytes(5);
+ /// assert_eq!(&bytes[..], &b"hello"[..]);
/// ```
- fn to_bytes(&mut self) -> crate::Bytes {
+ fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
use super::BufMut;
- let mut ret = crate::BytesMut::with_capacity(self.remaining());
- ret.put(self);
+
+ assert!(len <= self.remaining(), "`len` greater than remaining");
+
+ let mut ret = crate::BytesMut::with_capacity(len);
+ ret.put(self.take(len));
ret.freeze()
}
+
+ /// Creates an adaptor which will read at most `limit` bytes from `self`.
+ ///
+ /// This function returns a new instance of `Buf` which will read at most
+ /// `limit` bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use bytes::{Buf, BufMut};
+ ///
+ /// let mut buf = b"hello world"[..].take(5);
+ /// let mut dst = vec![];
+ ///
+ /// dst.put(&mut buf);
+ /// assert_eq!(dst, b"hello");
+ ///
+ /// let mut buf = buf.into_inner();
+ /// dst.clear();
+ /// dst.put(&mut buf);
+ /// assert_eq!(dst, b" world");
+ /// ```
+ fn take(self, limit: usize) -> Take<Self>
+ where
+ Self: Sized,
+ {
+ take::new(self, limit)
+ }
+
+ /// Creates an adaptor which will chain this buffer with another.
+ ///
+ /// The returned `Buf` instance will first consume all bytes from `self`.
+ /// Afterwards the output is equivalent to the output of next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use bytes::Buf;
+ ///
+ /// let mut chain = b"hello "[..].chain(&b"world"[..]);
+ ///
+ /// let full = chain.copy_to_bytes(11);
+ /// assert_eq!(full.chunk(), b"hello world");
+ /// ```
+ fn chain<U: Buf>(self, next: U) -> Chain<Self, U>
+ where
+ Self: Sized,
+ {
+ Chain::new(self, next)
+ }
+
+ /// Creates an adaptor which implements the `Read` trait for `self`.
+ ///
+ /// This function returns a new value which implements `Read` by adapting
+ /// the `Read` trait functions to the `Buf` trait functions. Given that
+ /// `Buf` operations are infallible, none of the `Read` functions will
+ /// return with `Err`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use bytes::{Bytes, Buf};
+ /// use std::io::Read;
+ ///
+ /// let buf = Bytes::from("hello world");
+ ///
+ /// let mut reader = buf.reader();
+ /// let mut dst = [0; 1024];
+ ///
+ /// let num = reader.read(&mut dst).unwrap();
+ ///
+ /// assert_eq!(11, num);
+ /// assert_eq!(&dst[..11], &b"hello world"[..]);
+ /// ```
+ #[cfg(feature = "std")]
+ fn reader(self) -> Reader<Self>
+ where
+ Self: Sized,
+ {
+ reader::new(self)
+ }
}
macro_rules! deref_forward_buf {
@@ -815,13 +908,13 @@ macro_rules! deref_forward_buf {
(**self).remaining()
}
- fn bytes(&self) -> &[u8] {
- (**self).bytes()
+ fn chunk(&self) -> &[u8] {
+ (**self).chunk()
}
#[cfg(feature = "std")]
- fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
- (**self).bytes_vectored(dst)
+ fn chunks_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
+ (**self).chunks_vectored(dst)
}
fn advance(&mut self, cnt: usize) {
@@ -908,8 +1001,8 @@ macro_rules! deref_forward_buf {
(**self).get_int_le(nbytes)
}
- fn to_bytes(&mut self) -> crate::Bytes {
- (**self).to_bytes()
+ fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
+ (**self).copy_to_bytes(len)
}
};
}
@@ -929,7 +1022,7 @@ impl Buf for &[u8] {
}
#[inline]
- fn bytes(&self) -> &[u8] {
+ fn chunk(&self) -> &[u8] {
self
}
@@ -939,35 +1032,6 @@ impl Buf for &[u8] {
}
}
-impl Buf for Option<[u8; 1]> {
- fn remaining(&self) -> usize {
- if self.is_some() {
- 1
- } else {
- 0
- }
- }
-
- fn bytes(&self) -> &[u8] {
- self.as_ref()
- .map(AsRef::as_ref)
- .unwrap_or(Default::default())
- }
-
- fn advance(&mut self, cnt: usize) {
- if cnt == 0 {
- return;
- }
-
- if self.is_none() {
- panic!("overflow");
- } else {
- assert_eq!(1, cnt);
- *self = None;
- }
- }
-}
-
#[cfg(feature = "std")]
impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
fn remaining(&self) -> usize {
@@ -981,7 +1045,7 @@ impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
len - pos as usize
}
- fn bytes(&self) -> &[u8] {
+ fn chunk(&self) -> &[u8] {
let len = self.get_ref().as_ref().len();
let pos = self.position();