mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-08 00:00:26 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3248c8807 | ||
|
|
c6c5b8fb54 | ||
|
|
7c3085aaec | ||
|
|
e64a123d00 | ||
|
|
e5304410a4 | ||
|
|
456221d165 | ||
|
|
f09c51c34e | ||
|
|
ad35fbef03 | ||
|
|
79f05591c9 |
@@ -39,6 +39,9 @@ matrix:
|
||||
# 128 bit numbers
|
||||
- env: EXTRA_ARGS="--features i128"
|
||||
|
||||
# `Either` impls
|
||||
- env: EXTRA_ARGS="--features either"
|
||||
|
||||
# WASM support
|
||||
- rust: beta
|
||||
script:
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
# 0.4.11 (November 17, 2018)
|
||||
|
||||
* Use raw pointers for potentially racy loads (#233).
|
||||
* Implement `BufRead` for `buf::Reader` (#232).
|
||||
* Documentation tweaks (#234).
|
||||
|
||||
# 0.4.10 (September 4, 2018)
|
||||
|
||||
* impl `Buf` and `BufMut` for `Either` (#225).
|
||||
* Add `Bytes::slice_ref` (#208).
|
||||
|
||||
# 0.4.9 (July 12, 2018)
|
||||
|
||||
* Add 128 bit number support behind a feature flag (#209).
|
||||
|
||||
+8
-2
@@ -1,11 +1,16 @@
|
||||
[package]
|
||||
|
||||
name = "bytes"
|
||||
version = "0.4.9" # don't forget to update html_root_url
|
||||
# When releasing to crates.io:
|
||||
# - Update html_root_url.
|
||||
# - Update CHANGELOG.md.
|
||||
# - Update doc URL.
|
||||
# - Create "v0.4.x" git tag.
|
||||
version = "0.4.11"
|
||||
license = "MIT"
|
||||
authors = ["Carl Lerche <[email protected]>"]
|
||||
description = "Types and traits for working with bytes"
|
||||
documentation = "https://carllerche.github.io/bytes/bytes"
|
||||
documentation = "https://docs.rs/bytes/0.4.11/bytes"
|
||||
homepage = "https://github.com/carllerche/bytes"
|
||||
repository = "https://github.com/carllerche/bytes"
|
||||
readme = "README.md"
|
||||
@@ -26,6 +31,7 @@ features = ["i128"]
|
||||
byteorder = "1.1.0"
|
||||
iovec = "0.1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
either = { version = "1.5", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_test = "1.0"
|
||||
|
||||
@@ -9,6 +9,9 @@ race:arc*Weak*drop
|
||||
# rust runtime logic.
|
||||
race:std*mpsc_queue
|
||||
|
||||
# Some test runtime races. Allocation should be race free
|
||||
race:alloc::alloc
|
||||
|
||||
# Not sure why this is warning, but it is in the test harness and not the library.
|
||||
race:TestEvent*clone
|
||||
race:test::run_tests_console::*closure
|
||||
@@ -19,3 +22,7 @@ race:__call_tls_dtors
|
||||
# `is_inline_or_static` is explicitly called concurrently without synchronization.
|
||||
# The safety explanation can be found in a comment.
|
||||
race:Inner::is_inline_or_static
|
||||
|
||||
# This ignores a false positive caused by `thread::park()`/`thread::unpark()`.
|
||||
# See: https://github.com/rust-lang/rust/pull/54806#issuecomment-436193353
|
||||
race:pthread_cond_destroy
|
||||
|
||||
+2
-1
@@ -91,7 +91,8 @@ pub trait Buf {
|
||||
fn remaining(&self) -> usize;
|
||||
|
||||
/// Returns a slice starting at the current position and of length between 0
|
||||
/// and `Buf::remaining()`.
|
||||
/// and `Buf::remaining()`. Note that this *can* return shorter slice (this allows
|
||||
/// non-continuous internal representation).
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
|
||||
+2
-1
@@ -121,7 +121,8 @@ pub trait BufMut {
|
||||
}
|
||||
|
||||
/// Returns a mutable slice starting at the current BufMut position and of
|
||||
/// length between 0 and `BufMut::remaining_mut()`.
|
||||
/// length between 0 and `BufMut::remaining_mut()`. Note that this *can* be shorter than the
|
||||
/// whole remainder of the buffer (this allows non-continuous implementation).
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
|
||||
@@ -86,3 +86,12 @@ impl<B: Buf + Sized> io::Read for Reader<B> {
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buf + Sized> io::BufRead for Reader<B> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
Ok(self.buf.bytes())
|
||||
}
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.buf.advance(amt)
|
||||
}
|
||||
}
|
||||
|
||||
+42
-2
@@ -576,6 +576,46 @@ impl Bytes {
|
||||
self.slice(0, end)
|
||||
}
|
||||
|
||||
/// Returns a slice of self that is equivalent to the given `subset`.
|
||||
///
|
||||
/// When processing a `Bytes` buffer with other tools, one often gets a
|
||||
/// `&[u8]` which is in fact a slice of the `Bytes`, i.e. a subset of it.
|
||||
/// This function turns that `&[u8]` into another `Bytes`, as if one had
|
||||
/// called `self.slice()` with the offsets that correspond to `subset`.
|
||||
///
|
||||
/// This operation is `O(1)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Bytes;
|
||||
///
|
||||
/// let bytes = Bytes::from(&b"012345678"[..]);
|
||||
/// let as_slice = bytes.as_ref();
|
||||
/// let subset = &as_slice[2..6];
|
||||
/// let subslice = bytes.slice_ref(&subset);
|
||||
/// assert_eq!(&subslice[..], b"2345");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Requires that the given `sub` slice is in fact contained within the
|
||||
/// `Bytes` buffer; otherwise this function will panic.
|
||||
pub fn slice_ref(&self, subset: &[u8]) -> Bytes {
|
||||
let bytes_p = self.as_ptr() as usize;
|
||||
let bytes_len = self.len();
|
||||
|
||||
let sub_p = subset.as_ptr() as usize;
|
||||
let sub_len = subset.len();
|
||||
|
||||
assert!(sub_p >= bytes_p);
|
||||
assert!(sub_p + sub_len <= bytes_p + bytes_len);
|
||||
|
||||
let sub_offset = sub_p - bytes_p;
|
||||
|
||||
self.slice(sub_offset, sub_offset + sub_len)
|
||||
}
|
||||
|
||||
/// Splits the bytes into two at the given index.
|
||||
///
|
||||
/// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
|
||||
@@ -2398,7 +2438,7 @@ impl Inner {
|
||||
#[inline]
|
||||
fn imp(arc: &AtomicPtr<Shared>) -> usize {
|
||||
unsafe {
|
||||
let p: &u8 = mem::transmute(arc);
|
||||
let p: *const u8 = mem::transmute(arc);
|
||||
(*p as usize) & KIND_MASK
|
||||
}
|
||||
}
|
||||
@@ -2407,7 +2447,7 @@ impl Inner {
|
||||
#[inline]
|
||||
fn imp(arc: &AtomicPtr<Shared>) -> usize {
|
||||
unsafe {
|
||||
let p: &usize = mem::transmute(arc);
|
||||
let p: *const usize = mem::transmute(arc);
|
||||
*p & KIND_MASK
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
extern crate either;
|
||||
|
||||
use {Buf, BufMut};
|
||||
|
||||
use self::either::Either;
|
||||
use self::either::Either::*;
|
||||
use iovec::IoVec;
|
||||
|
||||
impl<L, R> Buf for Either<L, R>
|
||||
where
|
||||
L: Buf,
|
||||
R: Buf,
|
||||
{
|
||||
fn remaining(&self) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.remaining(),
|
||||
Right(ref b) => b.remaining(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
match *self {
|
||||
Left(ref b) => b.bytes(),
|
||||
Right(ref b) => b.bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.bytes_vec(dst),
|
||||
Right(ref b) => b.bytes_vec(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.advance(cnt),
|
||||
Right(ref mut b) => b.advance(cnt),
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_to_slice(&mut self, dst: &mut [u8]) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.copy_to_slice(dst),
|
||||
Right(ref mut b) => b.copy_to_slice(dst),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> BufMut for Either<L, R>
|
||||
where
|
||||
L: BufMut,
|
||||
R: BufMut,
|
||||
{
|
||||
fn remaining_mut(&self) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.remaining_mut(),
|
||||
Right(ref b) => b.remaining_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
match *self {
|
||||
Left(ref mut b) => b.bytes_mut(),
|
||||
Right(ref mut b) => b.bytes_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
|
||||
match *self {
|
||||
Left(ref mut b) => b.bytes_vec_mut(dst),
|
||||
Right(ref mut b) => b.bytes_vec_mut(dst),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.advance_mut(cnt),
|
||||
Right(ref mut b) => b.advance_mut(cnt),
|
||||
}
|
||||
}
|
||||
|
||||
fn put_slice(&mut self, src: &[u8]) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.put_slice(src),
|
||||
Right(ref mut b) => b.put_slice(src),
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -69,7 +69,7 @@
|
||||
//! and `BufMut` are infallible.
|
||||
|
||||
#![deny(warnings, missing_docs, missing_debug_implementations)]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.4.9")]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.4.11")]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate iovec;
|
||||
@@ -99,3 +99,7 @@ pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
|
||||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
pub mod serde;
|
||||
|
||||
// Optional `Either` support
|
||||
#[cfg(feature = "either")]
|
||||
mod either;
|
||||
|
||||
@@ -717,3 +717,57 @@ fn from_iter_no_size_hint() {
|
||||
|
||||
assert_eq!(&actual[..], &expect[..]);
|
||||
}
|
||||
|
||||
fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) {
|
||||
let slice = &(bytes.as_ref()[start..end]);
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref_works() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
|
||||
test_slice_ref(&bytes, 0, 0, b"");
|
||||
test_slice_ref(&bytes, 0, 3, b"012");
|
||||
test_slice_ref(&bytes, 2, 6, b"2345");
|
||||
test_slice_ref(&bytes, 7, 9, b"78");
|
||||
test_slice_ref(&bytes, 9, 9, b"");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn slice_ref_empty() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
let slice = &(bytes.as_ref()[0..0]);
|
||||
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_a_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b"012345"[0..4];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn empty_slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
extern crate bytes;
|
||||
|
||||
use std::io::{BufRead, Cursor, Read};
|
||||
|
||||
use bytes::Buf;
|
||||
|
||||
#[test]
|
||||
fn read() {
|
||||
let buf1 = Cursor::new(b"hello ");
|
||||
let buf2 = Cursor::new(b"world");
|
||||
let buf = Buf::chain(buf1, buf2); // Disambiguate with Read::chain
|
||||
let mut buffer = Vec::new();
|
||||
buf.reader().read_to_end(&mut buffer).unwrap();
|
||||
assert_eq!(b"hello world", &buffer[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buf_read() {
|
||||
let buf1 = Cursor::new(b"hell");
|
||||
let buf2 = Cursor::new(b"o\nworld");
|
||||
let mut reader = Buf::chain(buf1, buf2).reader();
|
||||
let mut line = String::new();
|
||||
reader.read_line(&mut line).unwrap();
|
||||
assert_eq!("hello\n", &line);
|
||||
line.clear();
|
||||
reader.read_line(&mut line).unwrap();
|
||||
assert_eq!("world", &line);
|
||||
}
|
||||
Reference in New Issue
Block a user