├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── SECURITY.md ├── benches ├── buf.rs ├── bytes.rs └── bytes_mut.rs ├── ci ├── miri.sh ├── panic-abort.sh ├── test-stable.sh └── tsan.sh ├── clippy.toml ├── src ├── buf │ ├── buf_impl.rs │ ├── buf_mut.rs │ ├── chain.rs │ ├── iter.rs │ ├── limit.rs │ ├── mod.rs │ ├── reader.rs │ ├── take.rs │ ├── uninit_slice.rs │ ├── vec_deque.rs │ └── writer.rs ├── bytes.rs ├── bytes_mut.rs ├── fmt │ ├── debug.rs │ ├── hex.rs │ └── mod.rs ├── lib.rs ├── loom.rs └── serde.rs └── tests ├── test_buf.rs ├── test_buf_mut.rs ├── test_bytes.rs ├── test_bytes_odd_alloc.rs ├── test_bytes_vec_alloc.rs ├── test_chain.rs ├── test_debug.rs ├── test_iter.rs ├── test_limit.rs ├── test_reader.rs ├── test_serde.rs └── test_take.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | push: 8 | branches: 9 | - master 10 | schedule: 11 | - cron: '0 2 * * 0' 12 | 13 | env: 14 | RUSTFLAGS: -Dwarnings 15 | RUST_BACKTRACE: 1 16 | nightly: nightly-2024-09-15 17 | 18 | defaults: 19 | run: 20 | shell: bash 21 | 22 | jobs: 23 | # Check formatting 24 | rustfmt: 25 | name: rustfmt 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Install Rust 30 | run: rustup update stable 31 | - name: Check formatting 32 | run: cargo fmt --all --check 33 | 34 | # TODO 35 | # # Apply clippy lints 36 | # clippy: 37 | # name: clippy 38 | # runs-on: ubuntu-latest 39 | # steps: 40 | # - uses: actions/checkout@v4 41 | # - name: Apply clippy lints 42 | # run: cargo clippy --all-features 43 | 44 | # This represents the minimum Rust version supported by 45 | # Bytes. Updating this should be done in a dedicated PR. 46 | # 47 | # Tests are not run as tests may require newer versions of 48 | # rust. 49 | minrust: 50 | name: minrust 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v4 54 | - name: Install cargo-hack 55 | uses: taiki-e/install-action@cargo-hack 56 | - name: Check 57 | run: cargo hack check --feature-powerset --optional-deps --rust-version 58 | 59 | # Stable 60 | stable: 61 | name: stable 62 | strategy: 63 | matrix: 64 | os: 65 | - ubuntu-latest 66 | - ubuntu-22.04-arm # TODO: update to 24.04 when https://github.com/rust-lang/rust/issues/135867 solved 67 | - macos-latest 68 | - windows-latest 69 | runs-on: ${{ matrix.os }} 70 | steps: 71 | - uses: actions/checkout@v4 72 | - name: Install Rust 73 | # --no-self-update is necessary because the windows environment cannot self-update rustup.exe. 74 | run: rustup update stable --no-self-update 75 | - name: Install cargo-hack 76 | uses: taiki-e/install-action@cargo-hack 77 | - name: Test 78 | run: ci/test-stable.sh test 79 | 80 | # Nightly 81 | nightly: 82 | name: nightly 83 | runs-on: ubuntu-latest 84 | steps: 85 | - uses: actions/checkout@v4 86 | - name: Install Rust 87 | run: rustup update $nightly && rustup default $nightly 88 | - name: Install cargo-hack 89 | uses: taiki-e/install-action@cargo-hack 90 | - name: Test 91 | run: ci/test-stable.sh test 92 | 93 | panic-abort: 94 | name: panic=abort tests 95 | runs-on: ubuntu-latest 96 | steps: 97 | - uses: actions/checkout@v4 98 | - name: Install Rust 99 | run: rustup update $nightly && rustup default $nightly 100 | - name: Run tests with -Cpanic=abort 101 | run: ci/panic-abort.sh 102 | 103 | # Run tests on some extra platforms 104 | cross: 105 | name: cross 106 | strategy: 107 | matrix: 108 | include: 109 | - target: i686-unknown-linux-gnu 110 | os: ubuntu-latest 111 | - target: armv7-unknown-linux-gnueabihf 112 | os: ubuntu-22.04-arm # TODO: update to 24.04 when https://github.com/rust-lang/rust/issues/135867 solved 113 | - target: powerpc-unknown-linux-gnu 114 | os: ubuntu-latest 115 | - target: powerpc64-unknown-linux-gnu 116 | os: ubuntu-latest 117 | - target: wasm32-wasip1 118 | os: ubuntu-latest 119 | runs-on: ${{ matrix.os }} 120 | steps: 121 | - uses: actions/checkout@v4 122 | - name: Install Rust 123 | run: rustup update stable 124 | - uses: taiki-e/setup-cross-toolchain-action@v1 125 | with: 126 | target: ${{ matrix.target }} 127 | - name: Test 128 | run: cargo test --target ${{ matrix.target }} 129 | 130 | # Build for no_std environment. 131 | no-std: 132 | runs-on: ubuntu-latest 133 | steps: 134 | - uses: actions/checkout@v4 135 | - name: Install Rust 136 | run: rustup update stable 137 | - name: Install cargo-hack 138 | uses: taiki-e/install-action@cargo-hack 139 | # thumbv6m-none-eabi supports atomic, but not atomic CAS. 140 | # thumbv7m-none-eabi supports atomic CAS. 141 | - run: rustup target add thumbv6m-none-eabi thumbv7m-none-eabi 142 | # * --optional-deps is needed for serde feature 143 | # * --no-dev-deps is needed to avoid https://github.com/rust-lang/cargo/issues/4866 144 | - run: cargo hack build --target thumbv7m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps 145 | # A sound way to provide atomic CAS on platforms without native atomic CAS is system-dependent. 146 | # portable-atomic provides major ways via cfgs and accepts user-defined implementations via critical-section feature. 147 | - run: cargo hack build --target thumbv6m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps --features extra-platforms,extra-platforms/critical-section 148 | 149 | # Sanitizers 150 | tsan: 151 | name: tsan 152 | runs-on: ubuntu-latest 153 | steps: 154 | - uses: actions/checkout@v4 155 | - name: Install Rust 156 | run: rustup update $nightly && rustup default $nightly 157 | - name: Install rust-src 158 | run: rustup component add rust-src 159 | - name: ASAN / TSAN 160 | run: ci/tsan.sh 161 | 162 | miri: 163 | name: miri 164 | runs-on: ubuntu-latest 165 | steps: 166 | - uses: actions/checkout@v4 167 | - name: Install Rust 168 | run: rustup update $nightly && rustup default $nightly 169 | - name: Miri 170 | run: ci/miri.sh 171 | 172 | # Loom 173 | loom: 174 | name: loom 175 | runs-on: ubuntu-latest 176 | steps: 177 | - uses: actions/checkout@v4 178 | - name: Install Rust 179 | run: rustup update $nightly && rustup default $nightly 180 | - name: Loom tests 181 | run: RUSTFLAGS="--cfg loom -Dwarnings" cargo test --lib 182 | 183 | publish_docs: 184 | name: Publish Documentation 185 | needs: 186 | - rustfmt 187 | # - clippy 188 | - stable 189 | - nightly 190 | - minrust 191 | - cross 192 | - tsan 193 | - miri 194 | - loom 195 | runs-on: ubuntu-latest 196 | steps: 197 | - uses: actions/checkout@v4 198 | - name: Install Rust 199 | run: rustup update $nightly && rustup default $nightly 200 | - name: Build documentation 201 | run: cargo doc --no-deps --all-features 202 | env: 203 | RUSTDOCFLAGS: --cfg docsrs 204 | - name: Publish documentation 205 | run: | 206 | cd target/doc 207 | git init 208 | git add . 209 | git -c user.name='ci' -c user.email='ci' commit -m 'Deploy Bytes API documentation' 210 | git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages 211 | if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' && github.repository == 'tokio-rs/bytes' 212 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.10.1 (March 5th, 2025) 2 | 3 | ### Fixed 4 | 5 | - Fix memory leak when using `to_vec` with `Bytes::from_owner` (#773) 6 | 7 | # 1.10.0 (February 3rd, 2025) 8 | 9 | ### Added 10 | 11 | - Add feature to support platforms without atomic CAS (#467) 12 | - `try_get_*` methods for `Buf` trait (#753) 13 | - Implement `Buf::chunks_vectored` for `Take` (#617) 14 | - Implement `Buf::chunks_vectored` for `VecDeque` (#708) 15 | 16 | ### Fixed 17 | 18 | - Remove incorrect guarantee for `chunks_vectored` (#754) 19 | - Ensure that tests pass under `panic=abort` (#749) 20 | 21 | # 1.9.0 (November 27, 2024) 22 | 23 | ### Added 24 | 25 | - Add `Bytes::from_owner` to enable externally-allocated memory (#742) 26 | 27 | ### Documented 28 | 29 | - Fix typo in Buf::chunk() comment (#744) 30 | 31 | ### Internal changes 32 | 33 | - Replace BufMut::put with BufMut::put_slice in Writer impl (#745) 34 | - Rename hex_impl! to fmt_impl! and reuse it for fmt::Debug (#743) 35 | 36 | # 1.8.0 (October 21, 2024) 37 | 38 | - Guarantee address in `split_off`/`split_to` for empty slices (#740) 39 | 40 | # 1.7.2 (September 17, 2024) 41 | 42 | ### Fixed 43 | 44 | - Fix default impl of `Buf::{get_int, get_int_le}` (#732) 45 | 46 | ### Documented 47 | 48 | - Fix double spaces in comments and doc comments (#731) 49 | 50 | ### Internal changes 51 | 52 | - Ensure BytesMut::advance reduces capacity (#728) 53 | 54 | # 1.7.1 (August 1, 2024) 55 | 56 | This release reverts the following change due to a regression: 57 | 58 | - Reuse capacity when possible in `::advance` impl (#698) 59 | 60 | The revert can be found at #726. 61 | 62 | # 1.7.0 (July 31, 2024) 63 | 64 | ### Added 65 | 66 | - Add conversion from `Bytes` to `BytesMut` (#695, #710) 67 | - Add reclaim method without additional allocation (#686) 68 | 69 | ### Documented 70 | 71 | - Clarify how `BytesMut::zeroed` works (#714) 72 | - Clarify the behavior of `Buf::chunk` (#717) 73 | 74 | ### Changed 75 | 76 | - Change length condition of `BytesMut::truncate` 77 | - Reuse capacity when possible in `::advance` impl (#698) 78 | - Improve `must_use` suggestion of `BytesMut::split` (#699) 79 | 80 | ### Internal changes 81 | 82 | - Use `ManuallyDrop` instead of `mem::forget` (#678) 83 | - Don't set `len` in `BytesMut::reserve` (#682) 84 | - Optimize `Bytes::copy_to_bytes` (#688) 85 | - Refactor `BytesMut::truncate` (#694) 86 | - Refactor `BytesMut::resize` (#696) 87 | - Reorder assertion in `Bytes::split_to`, `Bytes::split_off` (#689, #693) 88 | - Use `offset_from` in more places (#705) 89 | - Correct the wrong usage of `IntoIter` (#707) 90 | 91 | # 1.6.1 (July 13, 2024) 92 | 93 | This release fixes a bug where `Bytes::is_unique` returns incorrect values when 94 | the `Bytes` originates from a shared `BytesMut`. (#718) 95 | 96 | # 1.6.0 (March 22, 2024) 97 | 98 | ### Added 99 | 100 | - Add `Bytes::is_unique` (#643) 101 | 102 | ### Documented 103 | 104 | - Fix changelog typo (#628) 105 | - Fix some spelling mistakes (#633) 106 | - Typo fix (#637) 107 | - Fix broken links (#639) 108 | - Add security policy (#649) 109 | 110 | ### Internal changes 111 | 112 | - Move comment to correct constant (#629) 113 | - Various cleanup (#635) 114 | - Simplify `UninitSlice::as_uninit_slice_mut()` logic (#644) 115 | - Use `self.` instead of `Self::` (#642) 116 | - `BytesMut`: Assert alignment of `Shared` (#652) 117 | - Remove unnecessary namespace qualifier (#660) 118 | - Remove an unnecessary else branch (#662) 119 | - Remove unreachable else branch (#661) 120 | - make parameter mut in `From` (#667) 121 | - Restore commented tests (#665) 122 | - Use `sub` instead of `offset` (#668) 123 | - Calculate original capacity only if necessary (#666) 124 | - `set_vec_pos` does not need a second parameter (#672) 125 | - `get_vec_pos`: use `&self` instead of `&mut self` (#670) 126 | - Refactor `split_at`/`split_to` (#663) 127 | - Use `Iterator` from the prelude (#673) 128 | - `copy_to_bytes`: Add panic section to docs (#676) 129 | - Remove redundant reserve call (#674) 130 | - Use `ManuallyDrop` instead of `mem::forget` (#675) 131 | 132 | 133 | # 1.5.0 (September 7, 2023) 134 | 135 | ### Added 136 | 137 | - Add `UninitSlice::{new,uninit}` (#598, #599) 138 | - Implement `BufMut` for `&mut [MaybeUninit]` (#597) 139 | 140 | ### Changed 141 | 142 | - Mark `BytesMut::extend_from_slice` as inline (#595) 143 | 144 | # 1.4.0 (January 31, 2023) 145 | 146 | ### Added 147 | 148 | - Make `IntoIter` constructor public (#581) 149 | 150 | ### Fixed 151 | 152 | - Avoid large reallocations when freezing `BytesMut` (#592) 153 | 154 | ### Documented 155 | 156 | - Document which functions require `std` (#591) 157 | - Fix duplicate "the the" typos (#585) 158 | 159 | # 1.3.0 (November 20, 2022) 160 | 161 | ### Added 162 | 163 | - Rename and expose `BytesMut::spare_capacity_mut` (#572) 164 | - Implement native-endian get and put functions for `Buf` and `BufMut` (#576) 165 | 166 | ### Fixed 167 | 168 | - Don't have important data in unused capacity when calling reserve (#563) 169 | 170 | ### Documented 171 | 172 | - `Bytes::new` etc should return `Self` not `Bytes` (#568) 173 | 174 | # 1.2.1 (July 30, 2022) 175 | 176 | ### Fixed 177 | 178 | - Fix unbounded memory growth when using `reserve` (#560) 179 | 180 | # 1.2.0 (July 19, 2022) 181 | 182 | ### Added 183 | 184 | - Add `BytesMut::zeroed` (#517) 185 | - Implement `Extend` for `BytesMut` (#527) 186 | - Add conversion from `BytesMut` to `Vec` (#543, #554) 187 | - Add conversion from `Bytes` to `Vec` (#547) 188 | - Add `UninitSlice::as_uninit_slice_mut()` (#548) 189 | - Add const to `Bytes::{len,is_empty}` (#514) 190 | 191 | ### Changed 192 | 193 | - Reuse vector in `BytesMut::reserve` (#539, #544) 194 | 195 | ### Fixed 196 | 197 | - Make miri happy (#515, #523, #542, #545, #553) 198 | - Make tsan happy (#541) 199 | - Fix `remaining_mut()` on chain (#488) 200 | - Fix amortized asymptotics of `BytesMut` (#555) 201 | 202 | ### Documented 203 | 204 | - Redraw layout diagram with box drawing characters (#539) 205 | - Clarify `BytesMut::unsplit` docs (#535) 206 | 207 | # 1.1.0 (August 25, 2021) 208 | 209 | ### Added 210 | 211 | - `BufMut::put_bytes(self, val, cnt)` (#487) 212 | - Implement `From>` for `Bytes` (#504) 213 | 214 | ### Changed 215 | 216 | - Override `put_slice` for `&mut [u8]` (#483) 217 | - Panic on integer overflow in `Chain::remaining` (#482) 218 | - Add inline tags to `UninitSlice` methods (#443) 219 | - Override `copy_to_bytes` for Chain and Take (#481) 220 | - Keep capacity when unsplit on empty other buf (#502) 221 | 222 | ### Documented 223 | 224 | - Clarify `BufMut` allocation guarantees (#501) 225 | - Clarify `BufMut::put_int` behavior (#486) 226 | - Clarify actions of `clear` and `truncate`. (#508) 227 | 228 | # 1.0.1 (January 11, 2021) 229 | 230 | ### Changed 231 | - mark `Vec::put_slice` with `#[inline]` (#459) 232 | 233 | ### Fixed 234 | - Fix deprecation warning (#457) 235 | - use `Box::into_raw` instead of `mem::forget`-in-disguise (#458) 236 | 237 | # 1.0.0 (December 22, 2020) 238 | 239 | ### Changed 240 | - Rename `Buf`/`BufMut` methods `bytes()` and `bytes_mut()` to `chunk()` and `chunk_mut()` (#450) 241 | 242 | ### Removed 243 | - remove unused Buf implementation. (#449) 244 | 245 | # 0.6.0 (October 21, 2020) 246 | 247 | API polish in preparation for a 1.0 release. 248 | 249 | ### Changed 250 | - `BufMut` is now an `unsafe` trait (#432). 251 | - `BufMut::bytes_mut()` returns `&mut UninitSlice`, a type owned by `bytes` to 252 | avoid undefined behavior (#433). 253 | - `Buf::copy_to_bytes(len)` replaces `Buf::into_bytes()` (#439). 254 | - `Buf`/`BufMut` utility methods are moved onto the trait and `*Ext` traits are 255 | removed (#431). 256 | 257 | ### Removed 258 | - `BufMut::bytes_vectored_mut()` (#430). 259 | - `new` methods on combinator types (#434). 260 | 261 | # 0.5.6 (July 13, 2020) 262 | 263 | - Improve `BytesMut` to reuse buffer when fully `advance`d. 264 | - Mark `BytesMut::{as_mut, set_len}` with `#[inline]`. 265 | - Relax synchronization when cloning in shared vtable of `Bytes`. 266 | - Move `loom` to `dev-dependencies`. 267 | 268 | # 0.5.5 (June 18, 2020) 269 | 270 | ### Added 271 | - Allow using the `serde` feature in `no_std` environments (#385). 272 | 273 | ### Fix 274 | - Fix `BufMut::advance_mut` to panic if advanced passed the capacity (#354).. 275 | - Fix `BytesMut::freeze` ignoring amount previously `advance`d (#352). 276 | 277 | # 0.5.4 (January 23, 2020) 278 | 279 | ### Added 280 | - Make `Bytes::new` a `const fn`. 281 | - Add `From` for `Bytes`. 282 | 283 | ### Fix 284 | - Fix reversed arguments in `PartialOrd` for `Bytes`. 285 | - Fix `Bytes::truncate` losing original capacity when repr is an unshared `Vec`. 286 | - Fix `Bytes::from(Vec)` when allocator gave `Vec` a pointer with LSB set. 287 | - Fix panic in `Bytes::slice_ref` if argument is an empty slice. 288 | 289 | # 0.5.3 (December 12, 2019) 290 | 291 | ### Added 292 | - `must_use` attributes to `split`, `split_off`, and `split_to` methods (#337). 293 | 294 | ### Fix 295 | - Potential freeing of a null pointer in `Bytes` when constructed with an empty `Vec` (#341, #342). 296 | - Calling `Bytes::truncate` with a size large than the length will no longer clear the `Bytes` (#333). 297 | 298 | # 0.5.2 (November 27, 2019) 299 | 300 | ### Added 301 | - `Limit` methods `into_inner`, `get_ref`, `get_mut`, `limit`, and `set_limit` (#325). 302 | 303 | # 0.5.1 (November 25, 2019) 304 | 305 | ### Fix 306 | - Growth documentation for `BytesMut` (#321) 307 | 308 | # 0.5.0 (November 25, 2019) 309 | 310 | ### Fix 311 | - Potential overflow in `copy_to_slice` 312 | 313 | ### Changed 314 | - Increased minimum supported Rust version to 1.39. 315 | - `Bytes` is now a "trait object", allowing for custom allocation strategies (#298) 316 | - `BytesMut` implicitly grows internal storage. `remaining_mut()` returns 317 | `usize::MAX` (#316). 318 | - `BufMut::bytes_mut` returns `&mut [MaybeUninit]` to reflect the unknown 319 | initialization state (#305). 320 | - `Buf` / `BufMut` implementations for `&[u8]` and `&mut [u8]` 321 | respectively (#261). 322 | - Move `Buf` / `BufMut` "extra" functions to an extension trait (#306). 323 | - `BufMutExt::limit` (#309). 324 | - `Bytes::slice` takes a `RangeBounds` argument (#265). 325 | - `Bytes::from_static` is now a `const fn` (#311). 326 | - A multitude of smaller performance optimizations. 327 | 328 | ### Added 329 | - `no_std` support (#281). 330 | - `get_*`, `put_*`, `get_*_le`, and `put_*le` accessors for handling byte order. 331 | - `BorrowMut` implementation for `BytesMut` (#185). 332 | 333 | ### Removed 334 | - `IntoBuf` (#288). 335 | - `Buf` implementation for `&str` (#301). 336 | - `byteorder` dependency (#280). 337 | - `iovec` dependency, use `std::IoSlice` instead (#263). 338 | - optional `either` dependency (#315). 339 | - optional `i128` feature -- now available on stable. (#276). 340 | 341 | # 0.4.12 (March 6, 2019) 342 | 343 | ### Added 344 | - Implement `FromIterator<&'a u8>` for `BytesMut`/`Bytes` (#244). 345 | - Implement `Buf` for `VecDeque` (#249). 346 | 347 | # 0.4.11 (November 17, 2018) 348 | 349 | * Use raw pointers for potentially racy loads (#233). 350 | * Implement `BufRead` for `buf::Reader` (#232). 351 | * Documentation tweaks (#234). 352 | 353 | # 0.4.10 (September 4, 2018) 354 | 355 | * impl `Buf` and `BufMut` for `Either` (#225). 356 | * Add `Bytes::slice_ref` (#208). 357 | 358 | # 0.4.9 (July 12, 2018) 359 | 360 | * Add 128 bit number support behind a feature flag (#209). 361 | * Implement `IntoBuf` for `&mut [u8]` 362 | 363 | # 0.4.8 (May 25, 2018) 364 | 365 | * Fix panic in `BytesMut` `FromIterator` implementation. 366 | * Bytes: Recycle space when reserving space in vec mode (#197). 367 | * Bytes: Add resize fn (#203). 368 | 369 | # 0.4.7 (April 27, 2018) 370 | 371 | * Make `Buf` and `BufMut` usable as trait objects (#186). 372 | * impl BorrowMut for BytesMut (#185). 373 | * Improve accessor performance (#195). 374 | 375 | # 0.4.6 (Janary 8, 2018) 376 | 377 | * Implement FromIterator for Bytes/BytesMut (#148). 378 | * Add `advance` fn to Bytes/BytesMut (#166). 379 | * Add `unsplit` fn to `BytesMut` (#162, #173). 380 | * Improvements to Bytes split fns (#92). 381 | 382 | # 0.4.5 (August 12, 2017) 383 | 384 | * Fix range bug in `Take::bytes` 385 | * Misc performance improvements 386 | * Add extra `PartialEq` implementations. 387 | * Add `Bytes::with_capacity` 388 | * Implement `AsMut[u8]` for `BytesMut` 389 | 390 | # 0.4.4 (May 26, 2017) 391 | 392 | * Add serde support behind feature flag 393 | * Add `extend_from_slice` on `Bytes` and `BytesMut` 394 | * Add `truncate` and `clear` on `Bytes` 395 | * Misc additional std trait implementations 396 | * Misc performance improvements 397 | 398 | # 0.4.3 (April 30, 2017) 399 | 400 | * Fix Vec::advance_mut bug 401 | * Bump minimum Rust version to 1.15 402 | * Misc performance tweaks 403 | 404 | # 0.4.2 (April 5, 2017) 405 | 406 | * Misc performance tweaks 407 | * Improved `Debug` implementation for `Bytes` 408 | * Avoid some incorrect assert panics 409 | 410 | # 0.4.1 (March 15, 2017) 411 | 412 | * Expose `buf` module and have most types available from there vs. root. 413 | * Implement `IntoBuf` for `T: Buf`. 414 | * Add `FromBuf` and `Buf::collect`. 415 | * Add iterator adapter for `Buf`. 416 | * Add scatter/gather support to `Buf` and `BufMut`. 417 | * Add `Buf::chain`. 418 | * Reduce allocations on repeated calls to `BytesMut::reserve`. 419 | * Implement `Debug` for more types. 420 | * Remove `Source` in favor of `IntoBuf`. 421 | * Implement `Extend` for `BytesMut`. 422 | 423 | 424 | # 0.4.0 (February 24, 2017) 425 | 426 | * Initial release 427 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "bytes" 4 | # When releasing to crates.io: 5 | # - Update CHANGELOG.md. 6 | # - Create "v1.x.y" git tag. 7 | version = "1.10.1" 8 | edition = "2018" 9 | rust-version = "1.39" 10 | license = "MIT" 11 | authors = [ 12 | "Carl Lerche ", 13 | "Sean McArthur ", 14 | ] 15 | description = "Types and traits for working with bytes" 16 | repository = "https://github.com/tokio-rs/bytes" 17 | readme = "README.md" 18 | keywords = ["buffers", "zero-copy", "io"] 19 | categories = ["network-programming", "data-structures"] 20 | 21 | [features] 22 | default = ["std"] 23 | std = [] 24 | 25 | [dependencies] 26 | serde = { version = "1.0.60", optional = true, default-features = false, features = ["alloc"] } 27 | # Use portable-atomic crate to support platforms without atomic CAS. 28 | # See "no_std support" section in readme for more information. 29 | # 30 | # Enable require-cas feature to provide a better error message if the end user forgets to use the cfg or feature. 31 | extra-platforms = { package = "portable-atomic", version = "1.3", optional = true, default-features = false, features = ["require-cas"] } 32 | 33 | [dev-dependencies] 34 | serde_test = "1.0" 35 | 36 | [target.'cfg(loom)'.dev-dependencies] 37 | loom = "0.7" 38 | 39 | [package.metadata.docs.rs] 40 | rustdoc-args = ["--cfg", "docsrs"] 41 | 42 | [lints.rust] 43 | unexpected_cfgs = { level = "warn", check-cfg = [ 44 | 'cfg(loom)', 45 | ] } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Carl Lerche 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bytes 2 | 3 | A utility library for working with bytes. 4 | 5 | [![Crates.io][crates-badge]][crates-url] 6 | [![Build Status][ci-badge]][ci-url] 7 | 8 | [crates-badge]: https://img.shields.io/crates/v/bytes.svg 9 | [crates-url]: https://crates.io/crates/bytes 10 | [ci-badge]: https://github.com/tokio-rs/bytes/workflows/CI/badge.svg 11 | [ci-url]: https://github.com/tokio-rs/bytes/actions 12 | 13 | [Documentation](https://docs.rs/bytes) 14 | 15 | ## Usage 16 | 17 | To use `bytes`, first add this to your `Cargo.toml`: 18 | 19 | ```toml 20 | [dependencies] 21 | bytes = "1" 22 | ``` 23 | 24 | Next, add this to your crate: 25 | 26 | ```rust 27 | use bytes::{Bytes, BytesMut, Buf, BufMut}; 28 | ``` 29 | 30 | ## no_std support 31 | 32 | To use `bytes` with no_std environment, disable the (enabled by default) `std` feature. 33 | 34 | ```toml 35 | [dependencies] 36 | bytes = { version = "1", default-features = false } 37 | ``` 38 | 39 | To use `bytes` with no_std environment without atomic CAS, such as thumbv6m, you also need to enable 40 | the `extra-platforms` feature. See the [documentation for the `portable-atomic` 41 | crate](https://docs.rs/portable-atomic) for more information. 42 | 43 | The MSRV when `extra-platforms` feature is enabled depends on the MSRV of `portable-atomic`. 44 | 45 | ## Serde support 46 | 47 | Serde support is optional and disabled by default. To enable use the feature `serde`. 48 | 49 | ```toml 50 | [dependencies] 51 | bytes = { version = "1", features = ["serde"] } 52 | ``` 53 | 54 | The MSRV when `serde` feature is enabled depends on the MSRV of `serde`. 55 | 56 | ## Building documentation 57 | 58 | When building the `bytes` documentation the `docsrs` option should be used, otherwise 59 | feature gates will not be shown. This requires a nightly toolchain: 60 | 61 | ``` 62 | RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc 63 | ``` 64 | 65 | ## License 66 | 67 | This project is licensed under the [MIT license](LICENSE). 68 | 69 | ### Contribution 70 | 71 | Unless you explicitly state otherwise, any contribution intentionally submitted 72 | for inclusion in `bytes` by you, shall be licensed as MIT, without any additional 73 | terms or conditions. 74 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Bytes is part of the Tokio project and uses the same security policy as [Tokio][tokio-security]. 4 | 5 | ## Report a security issue 6 | 7 | The process for reporting an issue is the same as for [Tokio][tokio-security]. This includes private reporting via security@tokio.rs. 8 | 9 | [tokio-security]: https://github.com/tokio-rs/tokio/security/policy 10 | -------------------------------------------------------------------------------- /benches/buf.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | #![warn(rust_2018_idioms)] 3 | 4 | extern crate test; 5 | 6 | use bytes::Buf; 7 | use test::Bencher; 8 | 9 | /// Dummy Buf implementation 10 | struct TestBuf { 11 | buf: &'static [u8], 12 | readlens: &'static [usize], 13 | init_pos: usize, 14 | pos: usize, 15 | readlen_pos: usize, 16 | readlen: usize, 17 | } 18 | impl TestBuf { 19 | fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBuf { 20 | let mut buf = TestBuf { 21 | buf, 22 | readlens, 23 | init_pos, 24 | pos: 0, 25 | readlen_pos: 0, 26 | readlen: 0, 27 | }; 28 | buf.reset(); 29 | buf 30 | } 31 | fn reset(&mut self) { 32 | self.pos = self.init_pos; 33 | self.readlen_pos = 0; 34 | self.next_readlen(); 35 | } 36 | /// Compute the length of the next read : 37 | /// - use the next value specified in readlens (capped by remaining) if any 38 | /// - else the remaining 39 | fn next_readlen(&mut self) { 40 | self.readlen = self.buf.len() - self.pos; 41 | if let Some(readlen) = self.readlens.get(self.readlen_pos) { 42 | self.readlen = std::cmp::min(self.readlen, *readlen); 43 | self.readlen_pos += 1; 44 | } 45 | } 46 | } 47 | impl Buf for TestBuf { 48 | fn remaining(&self) -> usize { 49 | self.buf.len() - self.pos 50 | } 51 | fn advance(&mut self, cnt: usize) { 52 | self.pos += cnt; 53 | assert!(self.pos <= self.buf.len()); 54 | self.next_readlen(); 55 | } 56 | fn chunk(&self) -> &[u8] { 57 | if self.readlen == 0 { 58 | Default::default() 59 | } else { 60 | &self.buf[self.pos..self.pos + self.readlen] 61 | } 62 | } 63 | } 64 | 65 | /// Dummy Buf implementation 66 | /// version with methods forced to not be inlined (to simulate costly calls) 67 | struct TestBufC { 68 | inner: TestBuf, 69 | } 70 | impl TestBufC { 71 | fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBufC { 72 | TestBufC { 73 | inner: TestBuf::new(buf, readlens, init_pos), 74 | } 75 | } 76 | fn reset(&mut self) { 77 | self.inner.reset() 78 | } 79 | } 80 | impl Buf for TestBufC { 81 | #[inline(never)] 82 | fn remaining(&self) -> usize { 83 | self.inner.remaining() 84 | } 85 | #[inline(never)] 86 | fn advance(&mut self, cnt: usize) { 87 | self.inner.advance(cnt) 88 | } 89 | #[inline(never)] 90 | fn chunk(&self) -> &[u8] { 91 | self.inner.chunk() 92 | } 93 | } 94 | 95 | macro_rules! bench { 96 | ($fname:ident, testbuf $testbuf:ident $readlens:expr, $method:ident $(,$arg:expr)*) => ( 97 | #[bench] 98 | fn $fname(b: &mut Bencher) { 99 | let mut bufs = [ 100 | $testbuf::new(&[1u8; 8+0], $readlens, 0), 101 | $testbuf::new(&[1u8; 8+1], $readlens, 1), 102 | $testbuf::new(&[1u8; 8+2], $readlens, 2), 103 | $testbuf::new(&[1u8; 8+3], $readlens, 3), 104 | $testbuf::new(&[1u8; 8+4], $readlens, 4), 105 | $testbuf::new(&[1u8; 8+5], $readlens, 5), 106 | $testbuf::new(&[1u8; 8+6], $readlens, 6), 107 | $testbuf::new(&[1u8; 8+7], $readlens, 7), 108 | ]; 109 | b.iter(|| { 110 | for i in 0..8 { 111 | bufs[i].reset(); 112 | let buf: &mut dyn Buf = &mut bufs[i]; // type erasure 113 | test::black_box(buf.$method($($arg,)*)); 114 | } 115 | }) 116 | } 117 | ); 118 | ($fname:ident, slice, $method:ident $(,$arg:expr)*) => ( 119 | #[bench] 120 | fn $fname(b: &mut Bencher) { 121 | // buf must be long enough for one read of 8 bytes starting at pos 7 122 | let arr = [1u8; 8+7]; 123 | b.iter(|| { 124 | for i in 0..8 { 125 | let mut buf = &arr[i..]; 126 | let buf = &mut buf as &mut dyn Buf; // type erasure 127 | test::black_box(buf.$method($($arg,)*)); 128 | } 129 | }) 130 | } 131 | ); 132 | ($fname:ident, option) => ( 133 | #[bench] 134 | fn $fname(b: &mut Bencher) { 135 | let data = [1u8; 1]; 136 | b.iter(|| { 137 | for _ in 0..8 { 138 | let mut buf = Some(data); 139 | let buf = &mut buf as &mut dyn Buf; // type erasure 140 | test::black_box(buf.get_u8()); 141 | } 142 | }) 143 | } 144 | ); 145 | } 146 | 147 | macro_rules! bench_group { 148 | ($method:ident $(,$arg:expr)*) => ( 149 | bench!(slice, slice, $method $(,$arg)*); 150 | bench!(tbuf_1, testbuf TestBuf &[], $method $(,$arg)*); 151 | bench!(tbuf_1_costly, testbuf TestBufC &[], $method $(,$arg)*); 152 | bench!(tbuf_2, testbuf TestBuf &[1], $method $(,$arg)*); 153 | bench!(tbuf_2_costly, testbuf TestBufC &[1], $method $(,$arg)*); 154 | // bench!(tbuf_onebyone, testbuf TestBuf &[1,1,1,1,1,1,1,1], $method $(,$arg)*); 155 | // bench!(tbuf_onebyone_costly, testbuf TestBufC &[1,1,1,1,1,1,1,1], $method $(,$arg)*); 156 | ); 157 | } 158 | 159 | mod get_u8 { 160 | use super::*; 161 | bench_group!(get_u8); 162 | } 163 | mod get_u16 { 164 | use super::*; 165 | bench_group!(get_u16); 166 | } 167 | mod get_u32 { 168 | use super::*; 169 | bench_group!(get_u32); 170 | } 171 | mod get_u64 { 172 | use super::*; 173 | bench_group!(get_u64); 174 | } 175 | mod get_f32 { 176 | use super::*; 177 | bench_group!(get_f32); 178 | } 179 | mod get_f64 { 180 | use super::*; 181 | bench_group!(get_f64); 182 | } 183 | mod get_uint24 { 184 | use super::*; 185 | bench_group!(get_uint, 3); 186 | } 187 | -------------------------------------------------------------------------------- /benches/bytes.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | #![warn(rust_2018_idioms)] 3 | 4 | extern crate test; 5 | 6 | use bytes::Bytes; 7 | use test::Bencher; 8 | 9 | #[bench] 10 | fn deref_unique(b: &mut Bencher) { 11 | let buf = Bytes::from(vec![0; 1024]); 12 | 13 | b.iter(|| { 14 | for _ in 0..1024 { 15 | test::black_box(&buf[..]); 16 | } 17 | }) 18 | } 19 | 20 | #[bench] 21 | fn deref_shared(b: &mut Bencher) { 22 | let buf = Bytes::from(vec![0; 1024]); 23 | let _b2 = buf.clone(); 24 | 25 | b.iter(|| { 26 | for _ in 0..1024 { 27 | test::black_box(&buf[..]); 28 | } 29 | }) 30 | } 31 | 32 | #[bench] 33 | fn deref_static(b: &mut Bencher) { 34 | let buf = Bytes::from_static(b"hello world"); 35 | 36 | b.iter(|| { 37 | for _ in 0..1024 { 38 | test::black_box(&buf[..]); 39 | } 40 | }) 41 | } 42 | 43 | #[bench] 44 | fn clone_static(b: &mut Bencher) { 45 | let bytes = 46 | Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes()); 47 | 48 | b.iter(|| { 49 | for _ in 0..1024 { 50 | test::black_box(test::black_box(&bytes).clone()); 51 | } 52 | }) 53 | } 54 | 55 | #[bench] 56 | fn clone_shared(b: &mut Bencher) { 57 | let bytes = Bytes::from(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); 58 | 59 | b.iter(|| { 60 | for _ in 0..1024 { 61 | test::black_box(test::black_box(&bytes).clone()); 62 | } 63 | }) 64 | } 65 | 66 | #[bench] 67 | fn clone_arc_vec(b: &mut Bencher) { 68 | use std::sync::Arc; 69 | let bytes = Arc::new(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); 70 | 71 | b.iter(|| { 72 | for _ in 0..1024 { 73 | test::black_box(test::black_box(&bytes).clone()); 74 | } 75 | }) 76 | } 77 | 78 | #[bench] 79 | fn from_long_slice(b: &mut Bencher) { 80 | let data = [0u8; 128]; 81 | b.bytes = data.len() as u64; 82 | b.iter(|| { 83 | let buf = Bytes::copy_from_slice(&data[..]); 84 | test::black_box(buf); 85 | }) 86 | } 87 | 88 | #[bench] 89 | fn slice_empty(b: &mut Bencher) { 90 | b.iter(|| { 91 | // `clone` is to convert to ARC 92 | let b = Bytes::from(vec![17; 1024]).clone(); 93 | for i in 0..1000 { 94 | test::black_box(b.slice(i % 100..i % 100)); 95 | } 96 | }) 97 | } 98 | 99 | #[bench] 100 | fn slice_short_from_arc(b: &mut Bencher) { 101 | b.iter(|| { 102 | // `clone` is to convert to ARC 103 | let b = Bytes::from(vec![17; 1024]).clone(); 104 | for i in 0..1000 { 105 | test::black_box(b.slice(1..2 + i % 10)); 106 | } 107 | }) 108 | } 109 | 110 | #[bench] 111 | fn split_off_and_drop(b: &mut Bencher) { 112 | b.iter(|| { 113 | for _ in 0..1024 { 114 | let v = vec![10; 200]; 115 | let mut b = Bytes::from(v); 116 | test::black_box(b.split_off(100)); 117 | test::black_box(b); 118 | } 119 | }) 120 | } 121 | -------------------------------------------------------------------------------- /benches/bytes_mut.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | #![warn(rust_2018_idioms)] 3 | 4 | extern crate test; 5 | 6 | use bytes::{BufMut, BytesMut}; 7 | use test::Bencher; 8 | 9 | #[bench] 10 | fn alloc_small(b: &mut Bencher) { 11 | b.iter(|| { 12 | for _ in 0..1024 { 13 | test::black_box(BytesMut::with_capacity(12)); 14 | } 15 | }) 16 | } 17 | 18 | #[bench] 19 | fn alloc_mid(b: &mut Bencher) { 20 | b.iter(|| { 21 | test::black_box(BytesMut::with_capacity(128)); 22 | }) 23 | } 24 | 25 | #[bench] 26 | fn alloc_big(b: &mut Bencher) { 27 | b.iter(|| { 28 | test::black_box(BytesMut::with_capacity(4096)); 29 | }) 30 | } 31 | 32 | #[bench] 33 | fn deref_unique(b: &mut Bencher) { 34 | let mut buf = BytesMut::with_capacity(4096); 35 | buf.put(&[0u8; 1024][..]); 36 | 37 | b.iter(|| { 38 | for _ in 0..1024 { 39 | test::black_box(&buf[..]); 40 | } 41 | }) 42 | } 43 | 44 | #[bench] 45 | fn deref_unique_unroll(b: &mut Bencher) { 46 | let mut buf = BytesMut::with_capacity(4096); 47 | buf.put(&[0u8; 1024][..]); 48 | 49 | b.iter(|| { 50 | for _ in 0..128 { 51 | test::black_box(&buf[..]); 52 | test::black_box(&buf[..]); 53 | test::black_box(&buf[..]); 54 | test::black_box(&buf[..]); 55 | test::black_box(&buf[..]); 56 | test::black_box(&buf[..]); 57 | test::black_box(&buf[..]); 58 | test::black_box(&buf[..]); 59 | } 60 | }) 61 | } 62 | 63 | #[bench] 64 | fn deref_shared(b: &mut Bencher) { 65 | let mut buf = BytesMut::with_capacity(4096); 66 | buf.put(&[0u8; 1024][..]); 67 | let _b2 = buf.split_off(1024); 68 | 69 | b.iter(|| { 70 | for _ in 0..1024 { 71 | test::black_box(&buf[..]); 72 | } 73 | }) 74 | } 75 | 76 | #[bench] 77 | fn deref_two(b: &mut Bencher) { 78 | let mut buf1 = BytesMut::with_capacity(8); 79 | buf1.put(&[0u8; 8][..]); 80 | 81 | let mut buf2 = BytesMut::with_capacity(4096); 82 | buf2.put(&[0u8; 1024][..]); 83 | 84 | b.iter(|| { 85 | for _ in 0..512 { 86 | test::black_box(&buf1[..]); 87 | test::black_box(&buf2[..]); 88 | } 89 | }) 90 | } 91 | 92 | #[bench] 93 | fn clone_frozen(b: &mut Bencher) { 94 | let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]) 95 | .split() 96 | .freeze(); 97 | 98 | b.iter(|| { 99 | for _ in 0..1024 { 100 | test::black_box(&bytes.clone()); 101 | } 102 | }) 103 | } 104 | 105 | #[bench] 106 | fn alloc_write_split_to_mid(b: &mut Bencher) { 107 | b.iter(|| { 108 | let mut buf = BytesMut::with_capacity(128); 109 | buf.put_slice(&[0u8; 64]); 110 | test::black_box(buf.split_to(64)); 111 | }) 112 | } 113 | 114 | #[bench] 115 | fn drain_write_drain(b: &mut Bencher) { 116 | let data = [0u8; 128]; 117 | 118 | b.iter(|| { 119 | let mut buf = BytesMut::with_capacity(1024); 120 | let mut parts = Vec::with_capacity(8); 121 | 122 | for _ in 0..8 { 123 | buf.put(&data[..]); 124 | parts.push(buf.split_to(128)); 125 | } 126 | 127 | test::black_box(parts); 128 | }) 129 | } 130 | 131 | #[bench] 132 | fn fmt_write(b: &mut Bencher) { 133 | use std::fmt::Write; 134 | let mut buf = BytesMut::with_capacity(128); 135 | let s = "foo bar baz quux lorem ipsum dolor et"; 136 | 137 | b.bytes = s.len() as u64; 138 | b.iter(|| { 139 | let _ = write!(buf, "{}", s); 140 | test::black_box(&buf); 141 | unsafe { 142 | buf.set_len(0); 143 | } 144 | }) 145 | } 146 | 147 | #[bench] 148 | fn bytes_mut_extend(b: &mut Bencher) { 149 | let mut buf = BytesMut::with_capacity(256); 150 | let data = [33u8; 32]; 151 | 152 | b.bytes = data.len() as u64 * 4; 153 | b.iter(|| { 154 | for _ in 0..4 { 155 | buf.extend(&data); 156 | } 157 | test::black_box(&buf); 158 | unsafe { 159 | buf.set_len(0); 160 | } 161 | }); 162 | } 163 | 164 | // BufMut for BytesMut vs Vec 165 | 166 | #[bench] 167 | fn put_slice_bytes_mut(b: &mut Bencher) { 168 | let mut buf = BytesMut::with_capacity(256); 169 | let data = [33u8; 32]; 170 | 171 | b.bytes = data.len() as u64 * 4; 172 | b.iter(|| { 173 | for _ in 0..4 { 174 | buf.put_slice(&data); 175 | } 176 | test::black_box(&buf); 177 | unsafe { 178 | buf.set_len(0); 179 | } 180 | }); 181 | } 182 | 183 | #[bench] 184 | fn put_u8_bytes_mut(b: &mut Bencher) { 185 | let mut buf = BytesMut::with_capacity(256); 186 | let cnt = 128; 187 | 188 | b.bytes = cnt as u64; 189 | b.iter(|| { 190 | for _ in 0..cnt { 191 | buf.put_u8(b'x'); 192 | } 193 | test::black_box(&buf); 194 | unsafe { 195 | buf.set_len(0); 196 | } 197 | }); 198 | } 199 | 200 | #[bench] 201 | fn put_slice_vec(b: &mut Bencher) { 202 | let mut buf = Vec::::with_capacity(256); 203 | let data = [33u8; 32]; 204 | 205 | b.bytes = data.len() as u64 * 4; 206 | b.iter(|| { 207 | for _ in 0..4 { 208 | buf.put_slice(&data); 209 | } 210 | test::black_box(&buf); 211 | unsafe { 212 | buf.set_len(0); 213 | } 214 | }); 215 | } 216 | 217 | #[bench] 218 | fn put_u8_vec(b: &mut Bencher) { 219 | let mut buf = Vec::::with_capacity(256); 220 | let cnt = 128; 221 | 222 | b.bytes = cnt as u64; 223 | b.iter(|| { 224 | for _ in 0..cnt { 225 | buf.put_u8(b'x'); 226 | } 227 | test::black_box(&buf); 228 | unsafe { 229 | buf.set_len(0); 230 | } 231 | }); 232 | } 233 | 234 | #[bench] 235 | fn put_slice_vec_extend(b: &mut Bencher) { 236 | let mut buf = Vec::::with_capacity(256); 237 | let data = [33u8; 32]; 238 | 239 | b.bytes = data.len() as u64 * 4; 240 | b.iter(|| { 241 | for _ in 0..4 { 242 | buf.extend_from_slice(&data); 243 | } 244 | test::black_box(&buf); 245 | unsafe { 246 | buf.set_len(0); 247 | } 248 | }); 249 | } 250 | 251 | #[bench] 252 | fn put_u8_vec_push(b: &mut Bencher) { 253 | let mut buf = Vec::::with_capacity(256); 254 | let cnt = 128; 255 | 256 | b.bytes = cnt as u64; 257 | b.iter(|| { 258 | for _ in 0..cnt { 259 | buf.push(b'x'); 260 | } 261 | test::black_box(&buf); 262 | unsafe { 263 | buf.set_len(0); 264 | } 265 | }); 266 | } 267 | -------------------------------------------------------------------------------- /ci/miri.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | rustup component add miri 5 | cargo miri setup 6 | 7 | export MIRIFLAGS="-Zmiri-strict-provenance" 8 | 9 | cargo miri test 10 | cargo miri test --target mips64-unknown-linux-gnuabi64 11 | -------------------------------------------------------------------------------- /ci/panic-abort.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | RUSTFLAGS="$RUSTFLAGS -Cpanic=abort -Zpanic-abort-tests" cargo test --all-features --test '*' 5 | -------------------------------------------------------------------------------- /ci/test-stable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | cmd="${1:-test}" 6 | 7 | # Run with each feature 8 | # * --each-feature includes both default/no-default features 9 | # * --optional-deps is needed for serde feature 10 | cargo hack "${cmd}" --each-feature --optional-deps 11 | # Run with all features 12 | cargo "${cmd}" --all-features 13 | 14 | if [[ "${RUST_VERSION}" == "nightly"* ]]; then 15 | # Check benchmarks 16 | cargo check --benches 17 | 18 | # Check minimal versions 19 | # Remove dev-dependencies from Cargo.toml to prevent the next `cargo update` 20 | # from determining minimal versions based on dev-dependencies. 21 | cargo hack --remove-dev-deps --workspace 22 | # Update Cargo.lock to minimal version dependencies. 23 | cargo update -Z minimal-versions 24 | cargo check --all-features 25 | fi 26 | -------------------------------------------------------------------------------- /ci/tsan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0" 6 | 7 | # Run address sanitizer 8 | RUSTFLAGS="-Z sanitizer=address" \ 9 | cargo test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut 10 | 11 | # Run thread sanitizer 12 | RUSTFLAGS="-Z sanitizer=thread" \ 13 | cargo -Zbuild-std test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut 14 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.39" 2 | -------------------------------------------------------------------------------- /src/buf/chain.rs: -------------------------------------------------------------------------------- 1 | use crate::buf::{IntoIter, UninitSlice}; 2 | use crate::{Buf, BufMut}; 3 | 4 | #[cfg(feature = "std")] 5 | use std::io::IoSlice; 6 | 7 | /// A `Chain` sequences two buffers. 8 | /// 9 | /// `Chain` is an adapter that links two underlying buffers and provides a 10 | /// continuous view across both buffers. It is able to sequence either immutable 11 | /// buffers ([`Buf`] values) or mutable buffers ([`BufMut`] values). 12 | /// 13 | /// This struct is generally created by calling [`Buf::chain`]. Please see that 14 | /// function's documentation for more detail. 15 | /// 16 | /// # Examples 17 | /// 18 | /// ``` 19 | /// use bytes::{Bytes, Buf}; 20 | /// 21 | /// let mut buf = (&b"hello "[..]) 22 | /// .chain(&b"world"[..]); 23 | /// 24 | /// let full: Bytes = buf.copy_to_bytes(11); 25 | /// assert_eq!(full[..], b"hello world"[..]); 26 | /// ``` 27 | /// 28 | /// [`Buf::chain`]: Buf::chain 29 | #[derive(Debug)] 30 | pub struct Chain { 31 | a: T, 32 | b: U, 33 | } 34 | 35 | impl Chain { 36 | /// Creates a new `Chain` sequencing the provided values. 37 | pub(crate) fn new(a: T, b: U) -> Chain { 38 | Chain { a, b } 39 | } 40 | 41 | /// Gets a reference to the first underlying `Buf`. 42 | /// 43 | /// # Examples 44 | /// 45 | /// ``` 46 | /// use bytes::Buf; 47 | /// 48 | /// let buf = (&b"hello"[..]) 49 | /// .chain(&b"world"[..]); 50 | /// 51 | /// assert_eq!(buf.first_ref()[..], b"hello"[..]); 52 | /// ``` 53 | pub fn first_ref(&self) -> &T { 54 | &self.a 55 | } 56 | 57 | /// Gets a mutable reference to the first underlying `Buf`. 58 | /// 59 | /// # Examples 60 | /// 61 | /// ``` 62 | /// use bytes::Buf; 63 | /// 64 | /// let mut buf = (&b"hello"[..]) 65 | /// .chain(&b"world"[..]); 66 | /// 67 | /// buf.first_mut().advance(1); 68 | /// 69 | /// let full = buf.copy_to_bytes(9); 70 | /// assert_eq!(full, b"elloworld"[..]); 71 | /// ``` 72 | pub fn first_mut(&mut self) -> &mut T { 73 | &mut self.a 74 | } 75 | 76 | /// Gets a reference to the last underlying `Buf`. 77 | /// 78 | /// # Examples 79 | /// 80 | /// ``` 81 | /// use bytes::Buf; 82 | /// 83 | /// let buf = (&b"hello"[..]) 84 | /// .chain(&b"world"[..]); 85 | /// 86 | /// assert_eq!(buf.last_ref()[..], b"world"[..]); 87 | /// ``` 88 | pub fn last_ref(&self) -> &U { 89 | &self.b 90 | } 91 | 92 | /// Gets a mutable reference to the last underlying `Buf`. 93 | /// 94 | /// # Examples 95 | /// 96 | /// ``` 97 | /// use bytes::Buf; 98 | /// 99 | /// let mut buf = (&b"hello "[..]) 100 | /// .chain(&b"world"[..]); 101 | /// 102 | /// buf.last_mut().advance(1); 103 | /// 104 | /// let full = buf.copy_to_bytes(10); 105 | /// assert_eq!(full, b"hello orld"[..]); 106 | /// ``` 107 | pub fn last_mut(&mut self) -> &mut U { 108 | &mut self.b 109 | } 110 | 111 | /// Consumes this `Chain`, returning the underlying values. 112 | /// 113 | /// # Examples 114 | /// 115 | /// ``` 116 | /// use bytes::Buf; 117 | /// 118 | /// let chain = (&b"hello"[..]) 119 | /// .chain(&b"world"[..]); 120 | /// 121 | /// let (first, last) = chain.into_inner(); 122 | /// assert_eq!(first[..], b"hello"[..]); 123 | /// assert_eq!(last[..], b"world"[..]); 124 | /// ``` 125 | pub fn into_inner(self) -> (T, U) { 126 | (self.a, self.b) 127 | } 128 | } 129 | 130 | impl Buf for Chain 131 | where 132 | T: Buf, 133 | U: Buf, 134 | { 135 | fn remaining(&self) -> usize { 136 | self.a.remaining().saturating_add(self.b.remaining()) 137 | } 138 | 139 | fn chunk(&self) -> &[u8] { 140 | if self.a.has_remaining() { 141 | self.a.chunk() 142 | } else { 143 | self.b.chunk() 144 | } 145 | } 146 | 147 | fn advance(&mut self, mut cnt: usize) { 148 | let a_rem = self.a.remaining(); 149 | 150 | if a_rem != 0 { 151 | if a_rem >= cnt { 152 | self.a.advance(cnt); 153 | return; 154 | } 155 | 156 | // Consume what is left of a 157 | self.a.advance(a_rem); 158 | 159 | cnt -= a_rem; 160 | } 161 | 162 | self.b.advance(cnt); 163 | } 164 | 165 | #[cfg(feature = "std")] 166 | fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { 167 | let mut n = self.a.chunks_vectored(dst); 168 | n += self.b.chunks_vectored(&mut dst[n..]); 169 | n 170 | } 171 | 172 | fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { 173 | let a_rem = self.a.remaining(); 174 | if a_rem >= len { 175 | self.a.copy_to_bytes(len) 176 | } else if a_rem == 0 { 177 | self.b.copy_to_bytes(len) 178 | } else { 179 | assert!( 180 | len - a_rem <= self.b.remaining(), 181 | "`len` greater than remaining" 182 | ); 183 | let mut ret = crate::BytesMut::with_capacity(len); 184 | ret.put(&mut self.a); 185 | ret.put((&mut self.b).take(len - a_rem)); 186 | ret.freeze() 187 | } 188 | } 189 | } 190 | 191 | unsafe impl BufMut for Chain 192 | where 193 | T: BufMut, 194 | U: BufMut, 195 | { 196 | fn remaining_mut(&self) -> usize { 197 | self.a 198 | .remaining_mut() 199 | .saturating_add(self.b.remaining_mut()) 200 | } 201 | 202 | fn chunk_mut(&mut self) -> &mut UninitSlice { 203 | if self.a.has_remaining_mut() { 204 | self.a.chunk_mut() 205 | } else { 206 | self.b.chunk_mut() 207 | } 208 | } 209 | 210 | unsafe fn advance_mut(&mut self, mut cnt: usize) { 211 | let a_rem = self.a.remaining_mut(); 212 | 213 | if a_rem != 0 { 214 | if a_rem >= cnt { 215 | self.a.advance_mut(cnt); 216 | return; 217 | } 218 | 219 | // Consume what is left of a 220 | self.a.advance_mut(a_rem); 221 | 222 | cnt -= a_rem; 223 | } 224 | 225 | self.b.advance_mut(cnt); 226 | } 227 | } 228 | 229 | impl IntoIterator for Chain 230 | where 231 | T: Buf, 232 | U: Buf, 233 | { 234 | type Item = u8; 235 | type IntoIter = IntoIter>; 236 | 237 | fn into_iter(self) -> Self::IntoIter { 238 | IntoIter::new(self) 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/buf/iter.rs: -------------------------------------------------------------------------------- 1 | use crate::Buf; 2 | 3 | /// Iterator over the bytes contained by the buffer. 4 | /// 5 | /// # Examples 6 | /// 7 | /// Basic usage: 8 | /// 9 | /// ``` 10 | /// use bytes::Bytes; 11 | /// 12 | /// let buf = Bytes::from(&b"abc"[..]); 13 | /// let mut iter = buf.into_iter(); 14 | /// 15 | /// assert_eq!(iter.next(), Some(b'a')); 16 | /// assert_eq!(iter.next(), Some(b'b')); 17 | /// assert_eq!(iter.next(), Some(b'c')); 18 | /// assert_eq!(iter.next(), None); 19 | /// ``` 20 | #[derive(Debug)] 21 | pub struct IntoIter { 22 | inner: T, 23 | } 24 | 25 | impl IntoIter { 26 | /// Creates an iterator over the bytes contained by the buffer. 27 | /// 28 | /// # Examples 29 | /// 30 | /// ``` 31 | /// use bytes::Bytes; 32 | /// 33 | /// let buf = Bytes::from_static(b"abc"); 34 | /// let mut iter = buf.into_iter(); 35 | /// 36 | /// assert_eq!(iter.next(), Some(b'a')); 37 | /// assert_eq!(iter.next(), Some(b'b')); 38 | /// assert_eq!(iter.next(), Some(b'c')); 39 | /// assert_eq!(iter.next(), None); 40 | /// ``` 41 | pub fn new(inner: T) -> IntoIter { 42 | IntoIter { inner } 43 | } 44 | 45 | /// Consumes this `IntoIter`, returning the underlying value. 46 | /// 47 | /// # Examples 48 | /// 49 | /// ```rust 50 | /// use bytes::{Buf, Bytes}; 51 | /// 52 | /// let buf = Bytes::from(&b"abc"[..]); 53 | /// let mut iter = buf.into_iter(); 54 | /// 55 | /// assert_eq!(iter.next(), Some(b'a')); 56 | /// 57 | /// let buf = iter.into_inner(); 58 | /// assert_eq!(2, buf.remaining()); 59 | /// ``` 60 | pub fn into_inner(self) -> T { 61 | self.inner 62 | } 63 | 64 | /// Gets a reference to the underlying `Buf`. 65 | /// 66 | /// It is inadvisable to directly read from the underlying `Buf`. 67 | /// 68 | /// # Examples 69 | /// 70 | /// ```rust 71 | /// use bytes::{Buf, Bytes}; 72 | /// 73 | /// let buf = Bytes::from(&b"abc"[..]); 74 | /// let mut iter = buf.into_iter(); 75 | /// 76 | /// assert_eq!(iter.next(), Some(b'a')); 77 | /// 78 | /// assert_eq!(2, iter.get_ref().remaining()); 79 | /// ``` 80 | pub fn get_ref(&self) -> &T { 81 | &self.inner 82 | } 83 | 84 | /// Gets a mutable reference to the underlying `Buf`. 85 | /// 86 | /// It is inadvisable to directly read from the underlying `Buf`. 87 | /// 88 | /// # Examples 89 | /// 90 | /// ```rust 91 | /// use bytes::{Buf, BytesMut}; 92 | /// 93 | /// let buf = BytesMut::from(&b"abc"[..]); 94 | /// let mut iter = buf.into_iter(); 95 | /// 96 | /// assert_eq!(iter.next(), Some(b'a')); 97 | /// 98 | /// iter.get_mut().advance(1); 99 | /// 100 | /// assert_eq!(iter.next(), Some(b'c')); 101 | /// ``` 102 | pub fn get_mut(&mut self) -> &mut T { 103 | &mut self.inner 104 | } 105 | } 106 | 107 | impl Iterator for IntoIter { 108 | type Item = u8; 109 | 110 | fn next(&mut self) -> Option { 111 | if !self.inner.has_remaining() { 112 | return None; 113 | } 114 | 115 | let b = self.inner.chunk()[0]; 116 | self.inner.advance(1); 117 | 118 | Some(b) 119 | } 120 | 121 | fn size_hint(&self) -> (usize, Option) { 122 | let rem = self.inner.remaining(); 123 | (rem, Some(rem)) 124 | } 125 | } 126 | 127 | impl ExactSizeIterator for IntoIter {} 128 | -------------------------------------------------------------------------------- /src/buf/limit.rs: -------------------------------------------------------------------------------- 1 | use crate::buf::UninitSlice; 2 | use crate::BufMut; 3 | 4 | use core::cmp; 5 | 6 | /// A `BufMut` adapter which limits the amount of bytes that can be written 7 | /// to an underlying buffer. 8 | #[derive(Debug)] 9 | pub struct Limit { 10 | inner: T, 11 | limit: usize, 12 | } 13 | 14 | pub(super) fn new(inner: T, limit: usize) -> Limit { 15 | Limit { inner, limit } 16 | } 17 | 18 | impl Limit { 19 | /// Consumes this `Limit`, returning the underlying value. 20 | pub fn into_inner(self) -> T { 21 | self.inner 22 | } 23 | 24 | /// Gets a reference to the underlying `BufMut`. 25 | /// 26 | /// It is inadvisable to directly write to the underlying `BufMut`. 27 | pub fn get_ref(&self) -> &T { 28 | &self.inner 29 | } 30 | 31 | /// Gets a mutable reference to the underlying `BufMut`. 32 | /// 33 | /// It is inadvisable to directly write to the underlying `BufMut`. 34 | pub fn get_mut(&mut self) -> &mut T { 35 | &mut self.inner 36 | } 37 | 38 | /// Returns the maximum number of bytes that can be written 39 | /// 40 | /// # Note 41 | /// 42 | /// If the inner `BufMut` has fewer bytes than indicated by this method then 43 | /// that is the actual number of available bytes. 44 | pub fn limit(&self) -> usize { 45 | self.limit 46 | } 47 | 48 | /// Sets the maximum number of bytes that can be written. 49 | /// 50 | /// # Note 51 | /// 52 | /// If the inner `BufMut` has fewer bytes than `lim` then that is the actual 53 | /// number of available bytes. 54 | pub fn set_limit(&mut self, lim: usize) { 55 | self.limit = lim 56 | } 57 | } 58 | 59 | unsafe impl BufMut for Limit { 60 | fn remaining_mut(&self) -> usize { 61 | cmp::min(self.inner.remaining_mut(), self.limit) 62 | } 63 | 64 | fn chunk_mut(&mut self) -> &mut UninitSlice { 65 | let bytes = self.inner.chunk_mut(); 66 | let end = cmp::min(bytes.len(), self.limit); 67 | &mut bytes[..end] 68 | } 69 | 70 | unsafe fn advance_mut(&mut self, cnt: usize) { 71 | assert!(cnt <= self.limit); 72 | self.inner.advance_mut(cnt); 73 | self.limit -= cnt; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/buf/mod.rs: -------------------------------------------------------------------------------- 1 | //! Utilities for working with buffers. 2 | //! 3 | //! A buffer is any structure that contains a sequence of bytes. The bytes may 4 | //! or may not be stored in contiguous memory. This module contains traits used 5 | //! to abstract over buffers as well as utilities for working with buffer types. 6 | //! 7 | //! # `Buf`, `BufMut` 8 | //! 9 | //! These are the two foundational traits for abstractly working with buffers. 10 | //! They can be thought as iterators for byte structures. They offer additional 11 | //! performance over `Iterator` by providing an API optimized for byte slices. 12 | //! 13 | //! See [`Buf`] and [`BufMut`] for more details. 14 | //! 15 | //! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure) 16 | 17 | mod buf_impl; 18 | mod buf_mut; 19 | mod chain; 20 | mod iter; 21 | mod limit; 22 | #[cfg(feature = "std")] 23 | mod reader; 24 | mod take; 25 | mod uninit_slice; 26 | mod vec_deque; 27 | #[cfg(feature = "std")] 28 | mod writer; 29 | 30 | pub use self::buf_impl::Buf; 31 | pub use self::buf_mut::BufMut; 32 | pub use self::chain::Chain; 33 | pub use self::iter::IntoIter; 34 | pub use self::limit::Limit; 35 | pub use self::take::Take; 36 | pub use self::uninit_slice::UninitSlice; 37 | 38 | #[cfg(feature = "std")] 39 | pub use self::{reader::Reader, writer::Writer}; 40 | -------------------------------------------------------------------------------- /src/buf/reader.rs: -------------------------------------------------------------------------------- 1 | use crate::Buf; 2 | 3 | use std::{cmp, io}; 4 | 5 | /// A `Buf` adapter which implements `io::Read` for the inner value. 6 | /// 7 | /// This struct is generally created by calling `reader()` on `Buf`. See 8 | /// documentation of [`reader()`](Buf::reader) for more 9 | /// details. 10 | #[derive(Debug)] 11 | pub struct Reader { 12 | buf: B, 13 | } 14 | 15 | pub fn new(buf: B) -> Reader { 16 | Reader { buf } 17 | } 18 | 19 | impl Reader { 20 | /// Gets a reference to the underlying `Buf`. 21 | /// 22 | /// It is inadvisable to directly read from the underlying `Buf`. 23 | /// 24 | /// # Examples 25 | /// 26 | /// ```rust 27 | /// use bytes::Buf; 28 | /// 29 | /// let buf = b"hello world".reader(); 30 | /// 31 | /// assert_eq!(b"hello world", buf.get_ref()); 32 | /// ``` 33 | pub fn get_ref(&self) -> &B { 34 | &self.buf 35 | } 36 | 37 | /// Gets a mutable reference to the underlying `Buf`. 38 | /// 39 | /// It is inadvisable to directly read from the underlying `Buf`. 40 | pub fn get_mut(&mut self) -> &mut B { 41 | &mut self.buf 42 | } 43 | 44 | /// Consumes this `Reader`, returning the underlying value. 45 | /// 46 | /// # Examples 47 | /// 48 | /// ```rust 49 | /// use bytes::Buf; 50 | /// use std::io; 51 | /// 52 | /// let mut buf = b"hello world".reader(); 53 | /// let mut dst = vec![]; 54 | /// 55 | /// io::copy(&mut buf, &mut dst).unwrap(); 56 | /// 57 | /// let buf = buf.into_inner(); 58 | /// assert_eq!(0, buf.remaining()); 59 | /// ``` 60 | pub fn into_inner(self) -> B { 61 | self.buf 62 | } 63 | } 64 | 65 | impl io::Read for Reader { 66 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 67 | let len = cmp::min(self.buf.remaining(), dst.len()); 68 | 69 | Buf::copy_to_slice(&mut self.buf, &mut dst[0..len]); 70 | Ok(len) 71 | } 72 | } 73 | 74 | impl io::BufRead for Reader { 75 | fn fill_buf(&mut self) -> io::Result<&[u8]> { 76 | Ok(self.buf.chunk()) 77 | } 78 | fn consume(&mut self, amt: usize) { 79 | self.buf.advance(amt) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/buf/take.rs: -------------------------------------------------------------------------------- 1 | use crate::Buf; 2 | 3 | use core::cmp; 4 | 5 | #[cfg(feature = "std")] 6 | use std::io::IoSlice; 7 | 8 | /// A `Buf` adapter which limits the bytes read from an underlying buffer. 9 | /// 10 | /// This struct is generally created by calling `take()` on `Buf`. See 11 | /// documentation of [`take()`](Buf::take) for more details. 12 | #[derive(Debug)] 13 | pub struct Take { 14 | inner: T, 15 | limit: usize, 16 | } 17 | 18 | pub fn new(inner: T, limit: usize) -> Take { 19 | Take { inner, limit } 20 | } 21 | 22 | impl Take { 23 | /// Consumes this `Take`, returning the underlying value. 24 | /// 25 | /// # Examples 26 | /// 27 | /// ```rust 28 | /// use bytes::{Buf, BufMut}; 29 | /// 30 | /// let mut buf = b"hello world".take(2); 31 | /// let mut dst = vec![]; 32 | /// 33 | /// dst.put(&mut buf); 34 | /// assert_eq!(*dst, b"he"[..]); 35 | /// 36 | /// let mut buf = buf.into_inner(); 37 | /// 38 | /// dst.clear(); 39 | /// dst.put(&mut buf); 40 | /// assert_eq!(*dst, b"llo world"[..]); 41 | /// ``` 42 | pub fn into_inner(self) -> T { 43 | self.inner 44 | } 45 | 46 | /// Gets a reference to the underlying `Buf`. 47 | /// 48 | /// It is inadvisable to directly read from the underlying `Buf`. 49 | /// 50 | /// # Examples 51 | /// 52 | /// ```rust 53 | /// use bytes::Buf; 54 | /// 55 | /// let buf = b"hello world".take(2); 56 | /// 57 | /// assert_eq!(11, buf.get_ref().remaining()); 58 | /// ``` 59 | pub fn get_ref(&self) -> &T { 60 | &self.inner 61 | } 62 | 63 | /// Gets a mutable reference to the underlying `Buf`. 64 | /// 65 | /// It is inadvisable to directly read from the underlying `Buf`. 66 | /// 67 | /// # Examples 68 | /// 69 | /// ```rust 70 | /// use bytes::{Buf, BufMut}; 71 | /// 72 | /// let mut buf = b"hello world".take(2); 73 | /// let mut dst = vec![]; 74 | /// 75 | /// buf.get_mut().advance(2); 76 | /// 77 | /// dst.put(&mut buf); 78 | /// assert_eq!(*dst, b"ll"[..]); 79 | /// ``` 80 | pub fn get_mut(&mut self) -> &mut T { 81 | &mut self.inner 82 | } 83 | 84 | /// Returns the maximum number of bytes that can be read. 85 | /// 86 | /// # Note 87 | /// 88 | /// If the inner `Buf` has fewer bytes than indicated by this method then 89 | /// that is the actual number of available bytes. 90 | /// 91 | /// # Examples 92 | /// 93 | /// ```rust 94 | /// use bytes::Buf; 95 | /// 96 | /// let mut buf = b"hello world".take(2); 97 | /// 98 | /// assert_eq!(2, buf.limit()); 99 | /// assert_eq!(b'h', buf.get_u8()); 100 | /// assert_eq!(1, buf.limit()); 101 | /// ``` 102 | pub fn limit(&self) -> usize { 103 | self.limit 104 | } 105 | 106 | /// Sets the maximum number of bytes that can be read. 107 | /// 108 | /// # Note 109 | /// 110 | /// If the inner `Buf` has fewer bytes than `lim` then that is the actual 111 | /// number of available bytes. 112 | /// 113 | /// # Examples 114 | /// 115 | /// ```rust 116 | /// use bytes::{Buf, BufMut}; 117 | /// 118 | /// let mut buf = b"hello world".take(2); 119 | /// let mut dst = vec![]; 120 | /// 121 | /// dst.put(&mut buf); 122 | /// assert_eq!(*dst, b"he"[..]); 123 | /// 124 | /// dst.clear(); 125 | /// 126 | /// buf.set_limit(3); 127 | /// dst.put(&mut buf); 128 | /// assert_eq!(*dst, b"llo"[..]); 129 | /// ``` 130 | pub fn set_limit(&mut self, lim: usize) { 131 | self.limit = lim 132 | } 133 | } 134 | 135 | impl Buf for Take { 136 | fn remaining(&self) -> usize { 137 | cmp::min(self.inner.remaining(), self.limit) 138 | } 139 | 140 | fn chunk(&self) -> &[u8] { 141 | let bytes = self.inner.chunk(); 142 | &bytes[..cmp::min(bytes.len(), self.limit)] 143 | } 144 | 145 | fn advance(&mut self, cnt: usize) { 146 | assert!(cnt <= self.limit); 147 | self.inner.advance(cnt); 148 | self.limit -= cnt; 149 | } 150 | 151 | fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { 152 | assert!(len <= self.remaining(), "`len` greater than remaining"); 153 | 154 | let r = self.inner.copy_to_bytes(len); 155 | self.limit -= len; 156 | r 157 | } 158 | 159 | #[cfg(feature = "std")] 160 | fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { 161 | if self.limit == 0 { 162 | return 0; 163 | } 164 | 165 | const LEN: usize = 16; 166 | let mut slices: [IoSlice<'a>; LEN] = [ 167 | IoSlice::new(&[]), 168 | IoSlice::new(&[]), 169 | IoSlice::new(&[]), 170 | IoSlice::new(&[]), 171 | IoSlice::new(&[]), 172 | IoSlice::new(&[]), 173 | IoSlice::new(&[]), 174 | IoSlice::new(&[]), 175 | IoSlice::new(&[]), 176 | IoSlice::new(&[]), 177 | IoSlice::new(&[]), 178 | IoSlice::new(&[]), 179 | IoSlice::new(&[]), 180 | IoSlice::new(&[]), 181 | IoSlice::new(&[]), 182 | IoSlice::new(&[]), 183 | ]; 184 | 185 | let cnt = self 186 | .inner 187 | .chunks_vectored(&mut slices[..dst.len().min(LEN)]); 188 | let mut limit = self.limit; 189 | for (i, (dst, slice)) in dst[..cnt].iter_mut().zip(slices.iter()).enumerate() { 190 | if let Some(buf) = slice.get(..limit) { 191 | // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV. 192 | let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(buf) }; 193 | *dst = IoSlice::new(buf); 194 | return i + 1; 195 | } else { 196 | // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV. 197 | let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(slice) }; 198 | *dst = IoSlice::new(buf); 199 | limit -= slice.len(); 200 | } 201 | } 202 | cnt 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/buf/uninit_slice.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use core::mem::MaybeUninit; 3 | use core::ops::{ 4 | Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, 5 | }; 6 | 7 | /// Uninitialized byte slice. 8 | /// 9 | /// Returned by `BufMut::chunk_mut()`, the referenced byte slice may be 10 | /// uninitialized. The wrapper provides safe access without introducing 11 | /// undefined behavior. 12 | /// 13 | /// The safety invariants of this wrapper are: 14 | /// 15 | /// 1. Reading from an `UninitSlice` is undefined behavior. 16 | /// 2. Writing uninitialized bytes to an `UninitSlice` is undefined behavior. 17 | /// 18 | /// The difference between `&mut UninitSlice` and `&mut [MaybeUninit]` is 19 | /// that it is possible in safe code to write uninitialized bytes to an 20 | /// `&mut [MaybeUninit]`, which this type prohibits. 21 | #[repr(transparent)] 22 | pub struct UninitSlice([MaybeUninit]); 23 | 24 | impl UninitSlice { 25 | /// Creates a `&mut UninitSlice` wrapping a slice of initialised memory. 26 | /// 27 | /// # Examples 28 | /// 29 | /// ``` 30 | /// use bytes::buf::UninitSlice; 31 | /// 32 | /// let mut buffer = [0u8; 64]; 33 | /// let slice = UninitSlice::new(&mut buffer[..]); 34 | /// ``` 35 | #[inline] 36 | pub fn new(slice: &mut [u8]) -> &mut UninitSlice { 37 | unsafe { &mut *(slice as *mut [u8] as *mut [MaybeUninit] as *mut UninitSlice) } 38 | } 39 | 40 | /// Creates a `&mut UninitSlice` wrapping a slice of uninitialised memory. 41 | /// 42 | /// # Examples 43 | /// 44 | /// ``` 45 | /// use bytes::buf::UninitSlice; 46 | /// use core::mem::MaybeUninit; 47 | /// 48 | /// let mut buffer = [MaybeUninit::uninit(); 64]; 49 | /// let slice = UninitSlice::uninit(&mut buffer[..]); 50 | /// 51 | /// let mut vec = Vec::with_capacity(1024); 52 | /// let spare: &mut UninitSlice = vec.spare_capacity_mut().into(); 53 | /// ``` 54 | #[inline] 55 | pub fn uninit(slice: &mut [MaybeUninit]) -> &mut UninitSlice { 56 | unsafe { &mut *(slice as *mut [MaybeUninit] as *mut UninitSlice) } 57 | } 58 | 59 | fn uninit_ref(slice: &[MaybeUninit]) -> &UninitSlice { 60 | unsafe { &*(slice as *const [MaybeUninit] as *const UninitSlice) } 61 | } 62 | 63 | /// Create a `&mut UninitSlice` from a pointer and a length. 64 | /// 65 | /// # Safety 66 | /// 67 | /// The caller must ensure that `ptr` references a valid memory region owned 68 | /// by the caller representing a byte slice for the duration of `'a`. 69 | /// 70 | /// # Examples 71 | /// 72 | /// ``` 73 | /// use bytes::buf::UninitSlice; 74 | /// 75 | /// let bytes = b"hello world".to_vec(); 76 | /// let ptr = bytes.as_ptr() as *mut _; 77 | /// let len = bytes.len(); 78 | /// 79 | /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) }; 80 | /// ``` 81 | #[inline] 82 | pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice { 83 | let maybe_init: &mut [MaybeUninit] = 84 | core::slice::from_raw_parts_mut(ptr as *mut _, len); 85 | Self::uninit(maybe_init) 86 | } 87 | 88 | /// Write a single byte at the specified offset. 89 | /// 90 | /// # Panics 91 | /// 92 | /// The function panics if `index` is out of bounds. 93 | /// 94 | /// # Examples 95 | /// 96 | /// ``` 97 | /// use bytes::buf::UninitSlice; 98 | /// 99 | /// let mut data = [b'f', b'o', b'o']; 100 | /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 101 | /// 102 | /// slice.write_byte(0, b'b'); 103 | /// 104 | /// assert_eq!(b"boo", &data[..]); 105 | /// ``` 106 | #[inline] 107 | pub fn write_byte(&mut self, index: usize, byte: u8) { 108 | assert!(index < self.len()); 109 | 110 | unsafe { self[index..].as_mut_ptr().write(byte) } 111 | } 112 | 113 | /// Copies bytes from `src` into `self`. 114 | /// 115 | /// The length of `src` must be the same as `self`. 116 | /// 117 | /// # Panics 118 | /// 119 | /// The function panics if `src` has a different length than `self`. 120 | /// 121 | /// # Examples 122 | /// 123 | /// ``` 124 | /// use bytes::buf::UninitSlice; 125 | /// 126 | /// let mut data = [b'f', b'o', b'o']; 127 | /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 128 | /// 129 | /// slice.copy_from_slice(b"bar"); 130 | /// 131 | /// assert_eq!(b"bar", &data[..]); 132 | /// ``` 133 | #[inline] 134 | pub fn copy_from_slice(&mut self, src: &[u8]) { 135 | use core::ptr; 136 | 137 | assert_eq!(self.len(), src.len()); 138 | 139 | unsafe { 140 | ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len()); 141 | } 142 | } 143 | 144 | /// Return a raw pointer to the slice's buffer. 145 | /// 146 | /// # Safety 147 | /// 148 | /// The caller **must not** read from the referenced memory and **must not** 149 | /// write **uninitialized** bytes to the slice either. 150 | /// 151 | /// # Examples 152 | /// 153 | /// ``` 154 | /// use bytes::BufMut; 155 | /// 156 | /// let mut data = [0, 1, 2]; 157 | /// let mut slice = &mut data[..]; 158 | /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr(); 159 | /// ``` 160 | #[inline] 161 | pub fn as_mut_ptr(&mut self) -> *mut u8 { 162 | self.0.as_mut_ptr() as *mut _ 163 | } 164 | 165 | /// Return a `&mut [MaybeUninit]` to this slice's buffer. 166 | /// 167 | /// # Safety 168 | /// 169 | /// The caller **must not** read from the referenced memory and **must not** write 170 | /// **uninitialized** bytes to the slice either. This is because `BufMut` implementation 171 | /// that created the `UninitSlice` knows which parts are initialized. Writing uninitialized 172 | /// bytes to the slice may cause the `BufMut` to read those bytes and trigger undefined 173 | /// behavior. 174 | /// 175 | /// # Examples 176 | /// 177 | /// ``` 178 | /// use bytes::BufMut; 179 | /// 180 | /// let mut data = [0, 1, 2]; 181 | /// let mut slice = &mut data[..]; 182 | /// unsafe { 183 | /// let uninit_slice = BufMut::chunk_mut(&mut slice).as_uninit_slice_mut(); 184 | /// }; 185 | /// ``` 186 | #[inline] 187 | pub unsafe fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit] { 188 | &mut self.0 189 | } 190 | 191 | /// Returns the number of bytes in the slice. 192 | /// 193 | /// # Examples 194 | /// 195 | /// ``` 196 | /// use bytes::BufMut; 197 | /// 198 | /// let mut data = [0, 1, 2]; 199 | /// let mut slice = &mut data[..]; 200 | /// let len = BufMut::chunk_mut(&mut slice).len(); 201 | /// 202 | /// assert_eq!(len, 3); 203 | /// ``` 204 | #[inline] 205 | pub fn len(&self) -> usize { 206 | self.0.len() 207 | } 208 | } 209 | 210 | impl fmt::Debug for UninitSlice { 211 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 212 | fmt.debug_struct("UninitSlice[...]").finish() 213 | } 214 | } 215 | 216 | impl<'a> From<&'a mut [u8]> for &'a mut UninitSlice { 217 | fn from(slice: &'a mut [u8]) -> Self { 218 | UninitSlice::new(slice) 219 | } 220 | } 221 | 222 | impl<'a> From<&'a mut [MaybeUninit]> for &'a mut UninitSlice { 223 | fn from(slice: &'a mut [MaybeUninit]) -> Self { 224 | UninitSlice::uninit(slice) 225 | } 226 | } 227 | 228 | macro_rules! impl_index { 229 | ($($t:ty),*) => { 230 | $( 231 | impl Index<$t> for UninitSlice { 232 | type Output = UninitSlice; 233 | 234 | #[inline] 235 | fn index(&self, index: $t) -> &UninitSlice { 236 | UninitSlice::uninit_ref(&self.0[index]) 237 | } 238 | } 239 | 240 | impl IndexMut<$t> for UninitSlice { 241 | #[inline] 242 | fn index_mut(&mut self, index: $t) -> &mut UninitSlice { 243 | UninitSlice::uninit(&mut self.0[index]) 244 | } 245 | } 246 | )* 247 | }; 248 | } 249 | 250 | impl_index!( 251 | Range, 252 | RangeFrom, 253 | RangeFull, 254 | RangeInclusive, 255 | RangeTo, 256 | RangeToInclusive 257 | ); 258 | -------------------------------------------------------------------------------- /src/buf/vec_deque.rs: -------------------------------------------------------------------------------- 1 | use alloc::collections::VecDeque; 2 | #[cfg(feature = "std")] 3 | use std::io; 4 | 5 | use super::Buf; 6 | 7 | impl Buf for VecDeque { 8 | fn remaining(&self) -> usize { 9 | self.len() 10 | } 11 | 12 | fn chunk(&self) -> &[u8] { 13 | let (s1, s2) = self.as_slices(); 14 | if s1.is_empty() { 15 | s2 16 | } else { 17 | s1 18 | } 19 | } 20 | 21 | #[cfg(feature = "std")] 22 | fn chunks_vectored<'a>(&'a self, dst: &mut [io::IoSlice<'a>]) -> usize { 23 | if self.is_empty() || dst.is_empty() { 24 | return 0; 25 | } 26 | 27 | let (s1, s2) = self.as_slices(); 28 | dst[0] = io::IoSlice::new(s1); 29 | if s2.is_empty() || dst.len() == 1 { 30 | return 1; 31 | } 32 | 33 | dst[1] = io::IoSlice::new(s2); 34 | 2 35 | } 36 | 37 | fn advance(&mut self, cnt: usize) { 38 | self.drain(..cnt); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/buf/writer.rs: -------------------------------------------------------------------------------- 1 | use crate::BufMut; 2 | 3 | use std::{cmp, io}; 4 | 5 | /// A `BufMut` adapter which implements `io::Write` for the inner value. 6 | /// 7 | /// This struct is generally created by calling `writer()` on `BufMut`. See 8 | /// documentation of [`writer()`](BufMut::writer) for more 9 | /// details. 10 | #[derive(Debug)] 11 | pub struct Writer { 12 | buf: B, 13 | } 14 | 15 | pub fn new(buf: B) -> Writer { 16 | Writer { buf } 17 | } 18 | 19 | impl Writer { 20 | /// Gets a reference to the underlying `BufMut`. 21 | /// 22 | /// It is inadvisable to directly write to the underlying `BufMut`. 23 | /// 24 | /// # Examples 25 | /// 26 | /// ```rust 27 | /// use bytes::BufMut; 28 | /// 29 | /// let buf = Vec::with_capacity(1024).writer(); 30 | /// 31 | /// assert_eq!(1024, buf.get_ref().capacity()); 32 | /// ``` 33 | pub fn get_ref(&self) -> &B { 34 | &self.buf 35 | } 36 | 37 | /// Gets a mutable reference to the underlying `BufMut`. 38 | /// 39 | /// It is inadvisable to directly write to the underlying `BufMut`. 40 | /// 41 | /// # Examples 42 | /// 43 | /// ```rust 44 | /// use bytes::BufMut; 45 | /// 46 | /// let mut buf = vec![].writer(); 47 | /// 48 | /// buf.get_mut().reserve(1024); 49 | /// 50 | /// assert_eq!(1024, buf.get_ref().capacity()); 51 | /// ``` 52 | pub fn get_mut(&mut self) -> &mut B { 53 | &mut self.buf 54 | } 55 | 56 | /// Consumes this `Writer`, returning the underlying value. 57 | /// 58 | /// # Examples 59 | /// 60 | /// ```rust 61 | /// use bytes::BufMut; 62 | /// use std::io; 63 | /// 64 | /// let mut buf = vec![].writer(); 65 | /// let mut src = &b"hello world"[..]; 66 | /// 67 | /// io::copy(&mut src, &mut buf).unwrap(); 68 | /// 69 | /// let buf = buf.into_inner(); 70 | /// assert_eq!(*buf, b"hello world"[..]); 71 | /// ``` 72 | pub fn into_inner(self) -> B { 73 | self.buf 74 | } 75 | } 76 | 77 | impl io::Write for Writer { 78 | fn write(&mut self, src: &[u8]) -> io::Result { 79 | let n = cmp::min(self.buf.remaining_mut(), src.len()); 80 | 81 | self.buf.put_slice(&src[..n]); 82 | Ok(n) 83 | } 84 | 85 | fn flush(&mut self) -> io::Result<()> { 86 | Ok(()) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/fmt/debug.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Debug, Formatter, Result}; 2 | 3 | use super::BytesRef; 4 | use crate::{Bytes, BytesMut}; 5 | 6 | /// Alternative implementation of `std::fmt::Debug` for byte slice. 7 | /// 8 | /// Standard `Debug` implementation for `[u8]` is comma separated 9 | /// list of numbers. Since large amount of byte strings are in fact 10 | /// ASCII strings or contain a lot of ASCII strings (e. g. HTTP), 11 | /// it is convenient to print strings as ASCII when possible. 12 | impl Debug for BytesRef<'_> { 13 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 14 | write!(f, "b\"")?; 15 | for &b in self.0 { 16 | // https://doc.rust-lang.org/reference/tokens.html#byte-escapes 17 | if b == b'\n' { 18 | write!(f, "\\n")?; 19 | } else if b == b'\r' { 20 | write!(f, "\\r")?; 21 | } else if b == b'\t' { 22 | write!(f, "\\t")?; 23 | } else if b == b'\\' || b == b'"' { 24 | write!(f, "\\{}", b as char)?; 25 | } else if b == b'\0' { 26 | write!(f, "\\0")?; 27 | // ASCII printable 28 | } else if (0x20..0x7f).contains(&b) { 29 | write!(f, "{}", b as char)?; 30 | } else { 31 | write!(f, "\\x{:02x}", b)?; 32 | } 33 | } 34 | write!(f, "\"")?; 35 | Ok(()) 36 | } 37 | } 38 | 39 | fmt_impl!(Debug, Bytes); 40 | fmt_impl!(Debug, BytesMut); 41 | -------------------------------------------------------------------------------- /src/fmt/hex.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Formatter, LowerHex, Result, UpperHex}; 2 | 3 | use super::BytesRef; 4 | use crate::{Bytes, BytesMut}; 5 | 6 | impl LowerHex for BytesRef<'_> { 7 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 8 | for &b in self.0 { 9 | write!(f, "{:02x}", b)?; 10 | } 11 | Ok(()) 12 | } 13 | } 14 | 15 | impl UpperHex for BytesRef<'_> { 16 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 17 | for &b in self.0 { 18 | write!(f, "{:02X}", b)?; 19 | } 20 | Ok(()) 21 | } 22 | } 23 | 24 | fmt_impl!(LowerHex, Bytes); 25 | fmt_impl!(LowerHex, BytesMut); 26 | fmt_impl!(UpperHex, Bytes); 27 | fmt_impl!(UpperHex, BytesMut); 28 | -------------------------------------------------------------------------------- /src/fmt/mod.rs: -------------------------------------------------------------------------------- 1 | macro_rules! fmt_impl { 2 | ($tr:ident, $ty:ty) => { 3 | impl $tr for $ty { 4 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 5 | $tr::fmt(&BytesRef(self.as_ref()), f) 6 | } 7 | } 8 | }; 9 | } 10 | 11 | mod debug; 12 | mod hex; 13 | 14 | /// `BytesRef` is not a part of public API of bytes crate. 15 | struct BytesRef<'a>(&'a [u8]); 16 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] 2 | #![doc(test( 3 | no_crate_inject, 4 | attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) 5 | ))] 6 | #![no_std] 7 | #![cfg_attr(docsrs, feature(doc_cfg))] 8 | 9 | //! Provides abstractions for working with bytes. 10 | //! 11 | //! The `bytes` crate provides an efficient byte buffer structure 12 | //! ([`Bytes`]) and traits for working with buffer 13 | //! implementations ([`Buf`], [`BufMut`]). 14 | //! 15 | //! # `Bytes` 16 | //! 17 | //! `Bytes` is an efficient container for storing and operating on contiguous 18 | //! slices of memory. It is intended for use primarily in networking code, but 19 | //! could have applications elsewhere as well. 20 | //! 21 | //! `Bytes` values facilitate zero-copy network programming by allowing multiple 22 | //! `Bytes` objects to point to the same underlying memory. This is managed by 23 | //! using a reference count to track when the memory is no longer needed and can 24 | //! be freed. 25 | //! 26 | //! A `Bytes` handle can be created directly from an existing byte store (such as `&[u8]` 27 | //! or `Vec`), but usually a `BytesMut` is used first and written to. For 28 | //! example: 29 | //! 30 | //! ```rust 31 | //! use bytes::{BytesMut, BufMut}; 32 | //! 33 | //! let mut buf = BytesMut::with_capacity(1024); 34 | //! buf.put(&b"hello world"[..]); 35 | //! buf.put_u16(1234); 36 | //! 37 | //! let a = buf.split(); 38 | //! assert_eq!(a, b"hello world\x04\xD2"[..]); 39 | //! 40 | //! buf.put(&b"goodbye world"[..]); 41 | //! 42 | //! let b = buf.split(); 43 | //! assert_eq!(b, b"goodbye world"[..]); 44 | //! 45 | //! assert_eq!(buf.capacity(), 998); 46 | //! ``` 47 | //! 48 | //! In the above example, only a single buffer of 1024 is allocated. The handles 49 | //! `a` and `b` will share the underlying buffer and maintain indices tracking 50 | //! the view into the buffer represented by the handle. 51 | //! 52 | //! See the [struct docs](`Bytes`) for more details. 53 | //! 54 | //! # `Buf`, `BufMut` 55 | //! 56 | //! These two traits provide read and write access to buffers. The underlying 57 | //! storage may or may not be in contiguous memory. For example, `Bytes` is a 58 | //! buffer that guarantees contiguous memory, but a [rope] stores the bytes in 59 | //! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current 60 | //! position in the underlying byte storage. When bytes are read or written, the 61 | //! cursor is advanced. 62 | //! 63 | //! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure) 64 | //! 65 | //! ## Relation with `Read` and `Write` 66 | //! 67 | //! At first glance, it may seem that `Buf` and `BufMut` overlap in 68 | //! functionality with [`std::io::Read`] and [`std::io::Write`]. However, they 69 | //! serve different purposes. A buffer is the value that is provided as an 70 | //! argument to `Read::read` and `Write::write`. `Read` and `Write` may then 71 | //! perform a syscall, which has the potential of failing. Operations on `Buf` 72 | //! and `BufMut` are infallible. 73 | 74 | extern crate alloc; 75 | 76 | #[cfg(feature = "std")] 77 | extern crate std; 78 | 79 | pub mod buf; 80 | pub use crate::buf::{Buf, BufMut}; 81 | 82 | mod bytes; 83 | mod bytes_mut; 84 | mod fmt; 85 | mod loom; 86 | pub use crate::bytes::Bytes; 87 | pub use crate::bytes_mut::BytesMut; 88 | 89 | // Optional Serde support 90 | #[cfg(feature = "serde")] 91 | mod serde; 92 | 93 | #[inline(never)] 94 | #[cold] 95 | fn abort() -> ! { 96 | #[cfg(feature = "std")] 97 | { 98 | std::process::abort(); 99 | } 100 | 101 | #[cfg(not(feature = "std"))] 102 | { 103 | struct Abort; 104 | impl Drop for Abort { 105 | fn drop(&mut self) { 106 | panic!(); 107 | } 108 | } 109 | let _a = Abort; 110 | panic!("abort"); 111 | } 112 | } 113 | 114 | #[inline(always)] 115 | #[cfg(feature = "std")] 116 | fn saturating_sub_usize_u64(a: usize, b: u64) -> usize { 117 | use core::convert::TryFrom; 118 | match usize::try_from(b) { 119 | Ok(b) => a.saturating_sub(b), 120 | Err(_) => 0, 121 | } 122 | } 123 | 124 | #[inline(always)] 125 | #[cfg(feature = "std")] 126 | fn min_u64_usize(a: u64, b: usize) -> usize { 127 | use core::convert::TryFrom; 128 | match usize::try_from(a) { 129 | Ok(a) => usize::min(a, b), 130 | Err(_) => b, 131 | } 132 | } 133 | 134 | /// Error type for the `try_get_` methods of [`Buf`]. 135 | /// Indicates that there were not enough remaining 136 | /// bytes in the buffer while attempting 137 | /// to get a value from a [`Buf`] with one 138 | /// of the `try_get_` methods. 139 | #[derive(Debug, PartialEq, Eq)] 140 | pub struct TryGetError { 141 | /// The number of bytes necessary to get the value 142 | pub requested: usize, 143 | 144 | /// The number of bytes available in the buffer 145 | pub available: usize, 146 | } 147 | 148 | impl core::fmt::Display for TryGetError { 149 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { 150 | write!( 151 | f, 152 | "Not enough bytes remaining in buffer to read value (requested {} but only {} available)", 153 | self.requested, 154 | self.available 155 | ) 156 | } 157 | } 158 | 159 | #[cfg(feature = "std")] 160 | impl std::error::Error for TryGetError {} 161 | 162 | #[cfg(feature = "std")] 163 | impl From for std::io::Error { 164 | fn from(error: TryGetError) -> Self { 165 | std::io::Error::new(std::io::ErrorKind::Other, error) 166 | } 167 | } 168 | 169 | /// Panic with a nice error message. 170 | #[cold] 171 | fn panic_advance(error_info: &TryGetError) -> ! { 172 | panic!( 173 | "advance out of bounds: the len is {} but advancing by {}", 174 | error_info.available, error_info.requested 175 | ); 176 | } 177 | 178 | #[cold] 179 | fn panic_does_not_fit(size: usize, nbytes: usize) -> ! { 180 | panic!( 181 | "size too large: the integer type can fit {} bytes, but nbytes is {}", 182 | size, nbytes 183 | ); 184 | } 185 | 186 | /// Precondition: dst >= original 187 | /// 188 | /// The following line is equivalent to: 189 | /// 190 | /// ```rust,ignore 191 | /// self.ptr.as_ptr().offset_from(ptr) as usize; 192 | /// ``` 193 | /// 194 | /// But due to min rust is 1.39 and it is only stabilized 195 | /// in 1.47, we cannot use it. 196 | #[inline] 197 | fn offset_from(dst: *const u8, original: *const u8) -> usize { 198 | dst as usize - original as usize 199 | } 200 | -------------------------------------------------------------------------------- /src/loom.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(all(test, loom)))] 2 | pub(crate) mod sync { 3 | pub(crate) mod atomic { 4 | #[cfg(not(feature = "extra-platforms"))] 5 | pub(crate) use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; 6 | #[cfg(feature = "extra-platforms")] 7 | pub(crate) use extra_platforms::{AtomicPtr, AtomicUsize, Ordering}; 8 | 9 | pub(crate) trait AtomicMut { 10 | fn with_mut(&mut self, f: F) -> R 11 | where 12 | F: FnOnce(&mut *mut T) -> R; 13 | } 14 | 15 | impl AtomicMut for AtomicPtr { 16 | fn with_mut(&mut self, f: F) -> R 17 | where 18 | F: FnOnce(&mut *mut T) -> R, 19 | { 20 | f(self.get_mut()) 21 | } 22 | } 23 | } 24 | } 25 | 26 | #[cfg(all(test, loom))] 27 | pub(crate) mod sync { 28 | pub(crate) mod atomic { 29 | pub(crate) use loom::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; 30 | 31 | pub(crate) trait AtomicMut {} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | use super::{Bytes, BytesMut}; 2 | use alloc::string::String; 3 | use alloc::vec::Vec; 4 | use core::{cmp, fmt}; 5 | use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; 6 | 7 | macro_rules! serde_impl { 8 | ($ty:ident, $visitor_ty:ident, $from_slice:ident, $from_vec:ident) => { 9 | impl Serialize for $ty { 10 | #[inline] 11 | fn serialize(&self, serializer: S) -> Result 12 | where 13 | S: Serializer, 14 | { 15 | serializer.serialize_bytes(&self) 16 | } 17 | } 18 | 19 | struct $visitor_ty; 20 | 21 | impl<'de> de::Visitor<'de> for $visitor_ty { 22 | type Value = $ty; 23 | 24 | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 25 | formatter.write_str("byte array") 26 | } 27 | 28 | #[inline] 29 | fn visit_seq(self, mut seq: V) -> Result 30 | where 31 | V: de::SeqAccess<'de>, 32 | { 33 | let len = cmp::min(seq.size_hint().unwrap_or(0), 4096); 34 | let mut values: Vec = Vec::with_capacity(len); 35 | 36 | while let Some(value) = seq.next_element()? { 37 | values.push(value); 38 | } 39 | 40 | Ok($ty::$from_vec(values)) 41 | } 42 | 43 | #[inline] 44 | fn visit_bytes(self, v: &[u8]) -> Result 45 | where 46 | E: de::Error, 47 | { 48 | Ok($ty::$from_slice(v)) 49 | } 50 | 51 | #[inline] 52 | fn visit_byte_buf(self, v: Vec) -> Result 53 | where 54 | E: de::Error, 55 | { 56 | Ok($ty::$from_vec(v)) 57 | } 58 | 59 | #[inline] 60 | fn visit_str(self, v: &str) -> Result 61 | where 62 | E: de::Error, 63 | { 64 | Ok($ty::$from_slice(v.as_bytes())) 65 | } 66 | 67 | #[inline] 68 | fn visit_string(self, v: String) -> Result 69 | where 70 | E: de::Error, 71 | { 72 | Ok($ty::$from_vec(v.into_bytes())) 73 | } 74 | } 75 | 76 | impl<'de> Deserialize<'de> for $ty { 77 | #[inline] 78 | fn deserialize(deserializer: D) -> Result<$ty, D::Error> 79 | where 80 | D: Deserializer<'de>, 81 | { 82 | deserializer.deserialize_byte_buf($visitor_ty) 83 | } 84 | } 85 | }; 86 | } 87 | 88 | serde_impl!(Bytes, BytesVisitor, copy_from_slice, from); 89 | serde_impl!(BytesMut, BytesMutVisitor, from, from_vec); 90 | -------------------------------------------------------------------------------- /tests/test_buf.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use ::bytes::{Buf, Bytes, BytesMut}; 4 | use core::{cmp, mem}; 5 | use std::collections::VecDeque; 6 | #[cfg(feature = "std")] 7 | use std::io::IoSlice; 8 | 9 | // A random 64-byte ascii string, with the first 8 bytes altered to 10 | // give valid representations of f32 and f64 (making them easier to compare) 11 | // and negative signed numbers when interpreting as big endian 12 | // (testing Sign Extension for `Buf::get_int' and `Buf::get_int_ne`). 13 | const INPUT: &[u8] = b"\xffFqrjrDqPhvTc45vvq33f6bJrUtyHESuTeklWKgYd64xgzxJwvAkpYYnpNJyZSRn"; 14 | 15 | macro_rules! e { 16 | ($big_endian_val:expr, $little_endian_val:expr) => { 17 | if cfg!(target_endian = "big") { 18 | $big_endian_val 19 | } else { 20 | $little_endian_val 21 | } 22 | }; 23 | } 24 | 25 | macro_rules! buf_tests { 26 | ($make_input:ident) => { 27 | buf_tests!($make_input, true); 28 | }; 29 | ($make_input:ident, $checks_vectored_is_complete:expr) => { 30 | use super::*; 31 | 32 | #[test] 33 | fn empty_state() { 34 | let buf = $make_input(&[]); 35 | assert_eq!(buf.remaining(), 0); 36 | assert!(!buf.has_remaining()); 37 | assert!(buf.chunk().is_empty()); 38 | } 39 | 40 | #[test] 41 | fn fresh_state() { 42 | let buf = $make_input(INPUT); 43 | assert_eq!(buf.remaining(), 64); 44 | assert!(buf.has_remaining()); 45 | 46 | let chunk = buf.chunk(); 47 | assert!(chunk.len() <= 64); 48 | assert!(INPUT.starts_with(chunk)); 49 | } 50 | 51 | #[test] 52 | fn advance() { 53 | let mut buf = $make_input(INPUT); 54 | buf.advance(8); 55 | assert_eq!(buf.remaining(), 64 - 8); 56 | assert!(buf.has_remaining()); 57 | 58 | let chunk = buf.chunk(); 59 | assert!(chunk.len() <= 64 - 8); 60 | assert!(INPUT[8..].starts_with(chunk)); 61 | } 62 | 63 | #[test] 64 | fn advance_to_end() { 65 | let mut buf = $make_input(INPUT); 66 | buf.advance(64); 67 | assert_eq!(buf.remaining(), 0); 68 | assert!(!buf.has_remaining()); 69 | 70 | let chunk = buf.chunk(); 71 | assert!(chunk.is_empty()); 72 | } 73 | 74 | #[test] 75 | #[should_panic] 76 | fn advance_past_end() { 77 | let mut buf = $make_input(INPUT); 78 | buf.advance(65); 79 | } 80 | 81 | #[test] 82 | #[cfg(feature = "std")] 83 | fn chunks_vectored_empty() { 84 | let buf = $make_input(&[]); 85 | let mut bufs = [IoSlice::new(&[]); 16]; 86 | 87 | let n = buf.chunks_vectored(&mut bufs); 88 | assert_eq!(n, 0); 89 | assert!(bufs.iter().all(|buf| buf.is_empty())); 90 | } 91 | 92 | #[test] 93 | #[cfg(feature = "std")] 94 | fn chunks_vectored_is_complete() { 95 | let buf = $make_input(INPUT); 96 | let mut bufs = [IoSlice::new(&[]); 16]; 97 | 98 | let n = buf.chunks_vectored(&mut bufs); 99 | assert!(n > 0); 100 | assert!(n <= 16); 101 | 102 | let bufs_concat = bufs[..n] 103 | .iter() 104 | .flat_map(|b| b.iter().copied()) 105 | .collect::>(); 106 | if $checks_vectored_is_complete { 107 | assert_eq!(bufs_concat, INPUT); 108 | } else { 109 | // If this panics then `buf` implements `chunks_vectored`. 110 | // Remove the `false` argument from `buf_tests!` for that type. 111 | assert!(bufs_concat.len() < INPUT.len()); 112 | assert!(INPUT.starts_with(&bufs_concat)); 113 | } 114 | 115 | for i in n..16 { 116 | assert!(bufs[i].is_empty()); 117 | } 118 | } 119 | 120 | #[test] 121 | fn copy_to_slice() { 122 | let mut buf = $make_input(INPUT); 123 | 124 | let mut chunk = [0u8; 8]; 125 | buf.copy_to_slice(&mut chunk); 126 | assert_eq!(buf.remaining(), 64 - 8); 127 | assert!(buf.has_remaining()); 128 | assert_eq!(chunk, INPUT[..8]); 129 | 130 | let chunk = buf.chunk(); 131 | assert!(chunk.len() <= 64 - 8); 132 | assert!(INPUT[8..].starts_with(chunk)); 133 | } 134 | 135 | #[test] 136 | fn copy_to_slice_big() { 137 | let mut buf = $make_input(INPUT); 138 | 139 | let mut chunk = [0u8; 56]; 140 | buf.copy_to_slice(&mut chunk); 141 | assert_eq!(buf.remaining(), 64 - 56); 142 | assert!(buf.has_remaining()); 143 | assert_eq!(chunk, INPUT[..56]); 144 | 145 | let chunk = buf.chunk(); 146 | assert!(chunk.len() <= 64 - 56); 147 | assert!(INPUT[56..].starts_with(chunk)); 148 | } 149 | 150 | #[test] 151 | fn copy_to_slice_to_end() { 152 | let mut buf = $make_input(INPUT); 153 | 154 | let mut chunk = [0u8; 64]; 155 | buf.copy_to_slice(&mut chunk); 156 | assert_eq!(buf.remaining(), 0); 157 | assert!(!buf.has_remaining()); 158 | assert_eq!(chunk, INPUT); 159 | 160 | assert!(buf.chunk().is_empty()); 161 | } 162 | 163 | #[test] 164 | #[should_panic] 165 | fn copy_to_slice_overflow() { 166 | let mut buf = $make_input(INPUT); 167 | 168 | let mut chunk = [0u8; 65]; 169 | buf.copy_to_slice(&mut chunk); 170 | } 171 | 172 | #[test] 173 | fn copy_to_bytes() { 174 | let mut buf = $make_input(INPUT); 175 | 176 | let chunk = buf.copy_to_bytes(8); 177 | assert_eq!(buf.remaining(), 64 - 8); 178 | assert!(buf.has_remaining()); 179 | assert_eq!(chunk, INPUT[..8]); 180 | 181 | let chunk = buf.chunk(); 182 | assert!(chunk.len() <= 64 - 8); 183 | assert!(INPUT[8..].starts_with(chunk)); 184 | } 185 | 186 | #[test] 187 | fn copy_to_bytes_big() { 188 | let mut buf = $make_input(INPUT); 189 | 190 | let chunk = buf.copy_to_bytes(56); 191 | assert_eq!(buf.remaining(), 64 - 56); 192 | assert!(buf.has_remaining()); 193 | assert_eq!(chunk, INPUT[..56]); 194 | 195 | let chunk = buf.chunk(); 196 | assert!(chunk.len() <= 64 - 56); 197 | assert!(INPUT[56..].starts_with(chunk)); 198 | } 199 | 200 | #[test] 201 | fn copy_to_bytes_to_end() { 202 | let mut buf = $make_input(INPUT); 203 | 204 | let chunk = buf.copy_to_bytes(64); 205 | assert_eq!(buf.remaining(), 0); 206 | assert!(!buf.has_remaining()); 207 | assert_eq!(chunk, INPUT); 208 | 209 | assert!(buf.chunk().is_empty()); 210 | } 211 | 212 | #[test] 213 | #[should_panic] 214 | fn copy_to_bytes_overflow() { 215 | let mut buf = $make_input(INPUT); 216 | 217 | let _ = buf.copy_to_bytes(65); 218 | } 219 | 220 | buf_tests!(number $make_input, get_u8, get_u8_overflow, u8, get_u8, 0xff); 221 | buf_tests!(number $make_input, get_i8, get_i8_overflow, i8, get_i8, 0xffu8 as i8); 222 | buf_tests!(number $make_input, get_u16_be, get_u16_be_overflow, u16, get_u16, 0xff46); 223 | buf_tests!(number $make_input, get_u16_le, get_u16_le_overflow, u16, get_u16_le, 0x46ff); 224 | buf_tests!(number $make_input, get_u16_ne, get_u16_ne_overflow, u16, get_u16_ne, e!(0xff46, 0x46ff)); 225 | buf_tests!(number $make_input, get_i16_be, get_i16_be_overflow, i16, get_i16, 0xff46u16 as i16); 226 | buf_tests!(number $make_input, get_i16_le, get_i16_le_overflow, i16, get_i16_le, 0x46ff); 227 | buf_tests!(number $make_input, get_i16_ne, get_i16_ne_overflow, i16, get_i16_ne, e!(0xff46u16 as i16, 0x46ff)); 228 | buf_tests!(number $make_input, get_u32_be, get_u32_be_overflow, u32, get_u32, 0xff467172); 229 | buf_tests!(number $make_input, get_u32_le, get_u32_le_overflow, u32, get_u32_le, 0x727146ff); 230 | buf_tests!(number $make_input, get_u32_ne, get_u32_ne_overflow, u32, get_u32_ne, e!(0xff467172, 0x727146ff)); 231 | buf_tests!(number $make_input, get_i32_be, get_i32_be_overflow, i32, get_i32, 0xff467172u32 as i32); 232 | buf_tests!(number $make_input, get_i32_le, get_i32_le_overflow, i32, get_i32_le, 0x727146ff); 233 | buf_tests!(number $make_input, get_i32_ne, get_i32_ne_overflow, i32, get_i32_ne, e!(0xff467172u32 as i32, 0x727146ff)); 234 | buf_tests!(number $make_input, get_u64_be, get_u64_be_overflow, u64, get_u64, 0xff4671726a724471); 235 | buf_tests!(number $make_input, get_u64_le, get_u64_le_overflow, u64, get_u64_le, 0x7144726a727146ff); 236 | buf_tests!(number $make_input, get_u64_ne, get_u64_ne_overflow, u64, get_u64_ne, e!(0xff4671726a724471, 0x7144726a727146ff)); 237 | buf_tests!(number $make_input, get_i64_be, get_i64_be_overflow, i64, get_i64, 0xff4671726a724471u64 as i64); 238 | buf_tests!(number $make_input, get_i64_le, get_i64_le_overflow, i64, get_i64_le, 0x7144726a727146ff); 239 | buf_tests!(number $make_input, get_i64_ne, get_i64_ne_overflow, i64, get_i64_ne, e!(0xff4671726a724471u64 as i64, 0x7144726a727146ff)); 240 | buf_tests!(number $make_input, get_u128_be, get_u128_be_overflow, u128, get_u128, 0xff4671726a7244715068765463343576); 241 | buf_tests!(number $make_input, get_u128_le, get_u128_le_overflow, u128, get_u128_le, 0x76353463547668507144726a727146ff); 242 | buf_tests!(number $make_input, get_u128_ne, get_u128_ne_overflow, u128, get_u128_ne, e!(0xff4671726a7244715068765463343576, 0x76353463547668507144726a727146ff)); 243 | buf_tests!(number $make_input, get_i128_be, get_i128_be_overflow, i128, get_i128, 0xff4671726a7244715068765463343576u128 as i128); 244 | buf_tests!(number $make_input, get_i128_le, get_i128_le_overflow, i128, get_i128_le, 0x76353463547668507144726a727146ff); 245 | buf_tests!(number $make_input, get_i128_ne, get_i128_ne_overflow, i128, get_i128_ne, e!(0xff4671726a7244715068765463343576u128 as i128, 0x76353463547668507144726a727146ff)); 246 | buf_tests!(number $make_input, get_f32_be, get_f32_be_overflow, f32, get_f32, f32::from_bits(0xff467172)); 247 | buf_tests!(number $make_input, get_f32_le, get_f32_le_overflow, f32, get_f32_le, f32::from_bits(0x727146ff)); 248 | buf_tests!(number $make_input, get_f32_ne, get_f32_ne_overflow, f32, get_f32_ne, f32::from_bits(e!(0xff467172, 0x727146ff))); 249 | buf_tests!(number $make_input, get_f64_be, get_f64_be_overflow, f64, get_f64, f64::from_bits(0xff4671726a724471)); 250 | buf_tests!(number $make_input, get_f64_le, get_f64_le_overflow, f64, get_f64_le, f64::from_bits(0x7144726a727146ff)); 251 | buf_tests!(number $make_input, get_f64_ne, get_f64_ne_overflow, f64, get_f64_ne, f64::from_bits(e!(0xff4671726a724471, 0x7144726a727146ff))); 252 | 253 | buf_tests!(var_number $make_input, get_uint_be, get_uint_be_overflow, u64, get_uint, 3, 0xff4671); 254 | buf_tests!(var_number $make_input, get_uint_le, get_uint_le_overflow, u64, get_uint_le, 3, 0x7146ff); 255 | buf_tests!(var_number $make_input, get_uint_ne, get_uint_ne_overflow, u64, get_uint_ne, 3, e!(0xff4671, 0x7146ff)); 256 | buf_tests!(var_number $make_input, get_int_be, get_int_be_overflow, i64, get_int, 3, 0xffffffffffff4671u64 as i64); 257 | buf_tests!(var_number $make_input, get_int_le, get_int_le_overflow, i64, get_int_le, 3, 0x7146ff); 258 | buf_tests!(var_number $make_input, get_int_ne, get_int_ne_overflow, i64, get_int_ne, 3, e!(0xffffffffffff4671u64 as i64, 0x7146ff)); 259 | }; 260 | (number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $value:expr) => { 261 | #[test] 262 | fn $ok_name() { 263 | let mut buf = $make_input(INPUT); 264 | 265 | let value = buf.$method(); 266 | assert_eq!(buf.remaining(), 64 - mem::size_of::<$number>()); 267 | assert!(buf.has_remaining()); 268 | assert_eq!(value, $value); 269 | } 270 | 271 | #[test] 272 | #[should_panic] 273 | fn $panic_name() { 274 | let mut buf = $make_input(&[]); 275 | 276 | let _ = buf.$method(); 277 | } 278 | }; 279 | (var_number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $len:expr, $value:expr) => { 280 | #[test] 281 | fn $ok_name() { 282 | let mut buf = $make_input(INPUT); 283 | 284 | let value = buf.$method($len); 285 | assert_eq!(buf.remaining(), 64 - $len); 286 | assert!(buf.has_remaining()); 287 | assert_eq!(value, $value); 288 | } 289 | 290 | #[test] 291 | #[should_panic] 292 | fn $panic_name() { 293 | let mut buf = $make_input(&[]); 294 | 295 | let _ = buf.$method($len); 296 | } 297 | }; 298 | } 299 | 300 | mod u8_slice { 301 | fn make_input(buf: &'static [u8]) -> &'static [u8] { 302 | buf 303 | } 304 | 305 | buf_tests!(make_input); 306 | } 307 | 308 | mod bytes { 309 | fn make_input(buf: &'static [u8]) -> impl Buf { 310 | Bytes::from_static(buf) 311 | } 312 | 313 | buf_tests!(make_input); 314 | } 315 | 316 | mod bytes_mut { 317 | fn make_input(buf: &'static [u8]) -> impl Buf { 318 | BytesMut::from(buf) 319 | } 320 | 321 | buf_tests!(make_input); 322 | } 323 | 324 | mod vec_deque { 325 | fn make_input(buf: &'static [u8]) -> impl Buf { 326 | let mut deque = VecDeque::new(); 327 | 328 | if !buf.is_empty() { 329 | // Construct |b|some bytes|a| `VecDeque` 330 | let mid = buf.len() / 2; 331 | let (a, b) = buf.split_at(mid); 332 | 333 | deque.reserve_exact(buf.len() + 1); 334 | 335 | let extra_space = deque.capacity() - b.len() - 1; 336 | deque.resize(extra_space, 0); 337 | 338 | deque.extend(a); 339 | deque.drain(..extra_space); 340 | deque.extend(b); 341 | 342 | let (a, b) = deque.as_slices(); 343 | assert!( 344 | !a.is_empty(), 345 | "could not setup test - attempt to create discontiguous VecDeque failed" 346 | ); 347 | assert!( 348 | !b.is_empty(), 349 | "could not setup test - attempt to create discontiguous VecDeque failed" 350 | ); 351 | } 352 | 353 | deque 354 | } 355 | 356 | buf_tests!(make_input, true); 357 | } 358 | 359 | #[cfg(feature = "std")] 360 | mod cursor { 361 | use std::io::Cursor; 362 | 363 | fn make_input(buf: &'static [u8]) -> impl Buf { 364 | Cursor::new(buf) 365 | } 366 | 367 | buf_tests!(make_input); 368 | } 369 | 370 | mod box_bytes { 371 | fn make_input(buf: &'static [u8]) -> impl Buf { 372 | Box::new(Bytes::from_static(buf)) 373 | } 374 | 375 | buf_tests!(make_input); 376 | } 377 | 378 | mod chain_u8_slice { 379 | fn make_input(buf: &'static [u8]) -> impl Buf { 380 | let (a, b) = buf.split_at(buf.len() / 2); 381 | Buf::chain(a, b) 382 | } 383 | 384 | buf_tests!(make_input); 385 | } 386 | 387 | mod chain_small_big_u8_slice { 388 | fn make_input(buf: &'static [u8]) -> impl Buf { 389 | let mid = cmp::min(1, buf.len()); 390 | let (a, b) = buf.split_at(mid); 391 | Buf::chain(a, b) 392 | } 393 | 394 | buf_tests!(make_input); 395 | } 396 | 397 | mod chain_limited_slices { 398 | fn make_input(buf: &'static [u8]) -> impl Buf { 399 | let buf3 = &buf[cmp::min(buf.len(), 3)..]; 400 | let a = Buf::take(buf3, 0); 401 | let b = Buf::take(buf, 3); 402 | let c = Buf::take(buf3, usize::MAX); 403 | let d = buf; 404 | Buf::take(Buf::chain(Buf::chain(a, b), Buf::chain(c, d)), buf.len()) 405 | } 406 | 407 | buf_tests!(make_input, true); 408 | } 409 | 410 | #[allow(unused_allocation)] // This is intentional. 411 | #[test] 412 | fn test_deref_buf_forwards() { 413 | struct Special; 414 | 415 | impl Buf for Special { 416 | fn remaining(&self) -> usize { 417 | unreachable!("remaining"); 418 | } 419 | 420 | fn chunk(&self) -> &[u8] { 421 | unreachable!("chunk"); 422 | } 423 | 424 | fn advance(&mut self, _: usize) { 425 | unreachable!("advance"); 426 | } 427 | 428 | fn get_u8(&mut self) -> u8 { 429 | // specialized! 430 | b'x' 431 | } 432 | } 433 | 434 | // these should all use the specialized method 435 | assert_eq!(Special.get_u8(), b'x'); 436 | assert_eq!((&mut Special as &mut dyn Buf).get_u8(), b'x'); 437 | assert_eq!((Box::new(Special) as Box).get_u8(), b'x'); 438 | assert_eq!(Box::new(Special).get_u8(), b'x'); 439 | } 440 | -------------------------------------------------------------------------------- /tests/test_buf_mut.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::buf::UninitSlice; 4 | use bytes::{BufMut, BytesMut}; 5 | use core::fmt::Write; 6 | use core::mem::MaybeUninit; 7 | use core::usize; 8 | 9 | #[test] 10 | fn test_vec_as_mut_buf() { 11 | let mut buf = Vec::with_capacity(64); 12 | 13 | assert_eq!(buf.remaining_mut(), isize::MAX as usize); 14 | 15 | assert!(buf.chunk_mut().len() >= 64); 16 | 17 | buf.put(&b"zomg"[..]); 18 | 19 | assert_eq!(&buf, b"zomg"); 20 | 21 | assert_eq!(buf.remaining_mut(), isize::MAX as usize - 4); 22 | assert_eq!(buf.capacity(), 64); 23 | 24 | for _ in 0..16 { 25 | buf.put(&b"zomg"[..]); 26 | } 27 | 28 | assert_eq!(buf.len(), 68); 29 | } 30 | 31 | #[test] 32 | fn test_vec_put_bytes() { 33 | let mut buf = Vec::new(); 34 | buf.push(17); 35 | buf.put_bytes(19, 2); 36 | assert_eq!([17, 19, 19], &buf[..]); 37 | } 38 | 39 | #[test] 40 | fn test_put_u8() { 41 | let mut buf = Vec::with_capacity(8); 42 | buf.put_u8(33); 43 | assert_eq!(b"\x21", &buf[..]); 44 | } 45 | 46 | #[test] 47 | fn test_put_u16() { 48 | let mut buf = Vec::with_capacity(8); 49 | buf.put_u16(8532); 50 | assert_eq!(b"\x21\x54", &buf[..]); 51 | 52 | buf.clear(); 53 | buf.put_u16_le(8532); 54 | assert_eq!(b"\x54\x21", &buf[..]); 55 | } 56 | 57 | #[test] 58 | fn test_put_int() { 59 | let mut buf = Vec::with_capacity(8); 60 | buf.put_int(0x1020304050607080, 3); 61 | assert_eq!(b"\x60\x70\x80", &buf[..]); 62 | } 63 | 64 | #[test] 65 | #[should_panic] 66 | fn test_put_int_nbytes_overflow() { 67 | let mut buf = Vec::with_capacity(8); 68 | buf.put_int(0x1020304050607080, 9); 69 | } 70 | 71 | #[test] 72 | fn test_put_int_le() { 73 | let mut buf = Vec::with_capacity(8); 74 | buf.put_int_le(0x1020304050607080, 3); 75 | assert_eq!(b"\x80\x70\x60", &buf[..]); 76 | } 77 | 78 | #[test] 79 | #[should_panic] 80 | fn test_put_int_le_nbytes_overflow() { 81 | let mut buf = Vec::with_capacity(8); 82 | buf.put_int_le(0x1020304050607080, 9); 83 | } 84 | 85 | #[test] 86 | #[should_panic(expected = "advance out of bounds: the len is 8 but advancing by 12")] 87 | fn test_vec_advance_mut() { 88 | // Verify fix for #354 89 | let mut buf = Vec::with_capacity(8); 90 | unsafe { 91 | buf.advance_mut(12); 92 | } 93 | } 94 | 95 | #[test] 96 | fn test_clone() { 97 | let mut buf = BytesMut::with_capacity(100); 98 | buf.write_str("this is a test").unwrap(); 99 | let buf2 = buf.clone(); 100 | 101 | buf.write_str(" of our emergency broadcast system").unwrap(); 102 | assert!(buf != buf2); 103 | } 104 | 105 | fn do_test_slice_small(make: impl Fn(&mut [u8]) -> &mut T) 106 | where 107 | for<'r> &'r mut T: BufMut, 108 | { 109 | let mut buf = [b'X'; 8]; 110 | 111 | let mut slice = make(&mut buf[..]); 112 | slice.put_bytes(b'A', 2); 113 | slice.put_u8(b'B'); 114 | slice.put_slice(b"BCC"); 115 | assert_eq!(2, slice.remaining_mut()); 116 | assert_eq!(b"AABBCCXX", &buf[..]); 117 | 118 | let mut slice = make(&mut buf[..]); 119 | slice.put_u32(0x61626364); 120 | assert_eq!(4, slice.remaining_mut()); 121 | assert_eq!(b"abcdCCXX", &buf[..]); 122 | 123 | let mut slice = make(&mut buf[..]); 124 | slice.put_u32_le(0x30313233); 125 | assert_eq!(4, slice.remaining_mut()); 126 | assert_eq!(b"3210CCXX", &buf[..]); 127 | } 128 | 129 | fn do_test_slice_large(make: impl Fn(&mut [u8]) -> &mut T) 130 | where 131 | for<'r> &'r mut T: BufMut, 132 | { 133 | const LEN: usize = 100; 134 | const FILL: [u8; LEN] = [b'Y'; LEN]; 135 | 136 | let test = |fill: &dyn Fn(&mut &mut T, usize)| { 137 | for buf_len in 0..LEN { 138 | let mut buf = [b'X'; LEN]; 139 | for fill_len in 0..=buf_len { 140 | let mut slice = make(&mut buf[..buf_len]); 141 | fill(&mut slice, fill_len); 142 | assert_eq!(buf_len - fill_len, slice.remaining_mut()); 143 | let (head, tail) = buf.split_at(fill_len); 144 | assert_eq!(&FILL[..fill_len], head); 145 | assert!(tail.iter().all(|b| *b == b'X')); 146 | } 147 | } 148 | }; 149 | 150 | test(&|slice, fill_len| slice.put_slice(&FILL[..fill_len])); 151 | test(&|slice, fill_len| slice.put_bytes(FILL[0], fill_len)); 152 | } 153 | 154 | fn do_test_slice_put_slice_panics(make: impl Fn(&mut [u8]) -> &mut T) 155 | where 156 | for<'r> &'r mut T: BufMut, 157 | { 158 | let mut buf = [b'X'; 4]; 159 | let mut slice = make(&mut buf[..]); 160 | slice.put_slice(b"12345"); 161 | } 162 | 163 | fn do_test_slice_put_bytes_panics(make: impl Fn(&mut [u8]) -> &mut T) 164 | where 165 | for<'r> &'r mut T: BufMut, 166 | { 167 | let mut buf = [b'X'; 4]; 168 | let mut slice = make(&mut buf[..]); 169 | slice.put_bytes(b'1', 5); 170 | } 171 | 172 | #[test] 173 | fn test_slice_buf_mut_small() { 174 | do_test_slice_small(|x| x); 175 | } 176 | 177 | #[test] 178 | fn test_slice_buf_mut_large() { 179 | do_test_slice_large(|x| x); 180 | } 181 | 182 | #[test] 183 | #[should_panic] 184 | fn test_slice_buf_mut_put_slice_overflow() { 185 | do_test_slice_put_slice_panics(|x| x); 186 | } 187 | 188 | #[test] 189 | #[should_panic] 190 | fn test_slice_buf_mut_put_bytes_overflow() { 191 | do_test_slice_put_bytes_panics(|x| x); 192 | } 193 | 194 | fn make_maybe_uninit_slice(slice: &mut [u8]) -> &mut [MaybeUninit] { 195 | // SAFETY: [u8] has the same layout as [MaybeUninit]. 196 | unsafe { core::mem::transmute(slice) } 197 | } 198 | 199 | #[test] 200 | fn test_maybe_uninit_buf_mut_small() { 201 | do_test_slice_small(make_maybe_uninit_slice); 202 | } 203 | 204 | #[test] 205 | fn test_maybe_uninit_buf_mut_large() { 206 | do_test_slice_large(make_maybe_uninit_slice); 207 | } 208 | 209 | #[test] 210 | #[should_panic] 211 | fn test_maybe_uninit_buf_mut_put_slice_overflow() { 212 | do_test_slice_put_slice_panics(make_maybe_uninit_slice); 213 | } 214 | 215 | #[test] 216 | #[should_panic] 217 | fn test_maybe_uninit_buf_mut_put_bytes_overflow() { 218 | do_test_slice_put_bytes_panics(make_maybe_uninit_slice); 219 | } 220 | 221 | #[allow(unused_allocation)] // This is intentional. 222 | #[test] 223 | fn test_deref_bufmut_forwards() { 224 | struct Special; 225 | 226 | unsafe impl BufMut for Special { 227 | fn remaining_mut(&self) -> usize { 228 | unreachable!("remaining_mut"); 229 | } 230 | 231 | fn chunk_mut(&mut self) -> &mut UninitSlice { 232 | unreachable!("chunk_mut"); 233 | } 234 | 235 | unsafe fn advance_mut(&mut self, _: usize) { 236 | unreachable!("advance"); 237 | } 238 | 239 | fn put_u8(&mut self, _: u8) { 240 | // specialized! 241 | } 242 | } 243 | 244 | // these should all use the specialized method 245 | Special.put_u8(b'x'); 246 | (&mut Special as &mut dyn BufMut).put_u8(b'x'); 247 | (Box::new(Special) as Box).put_u8(b'x'); 248 | Box::new(Special).put_u8(b'x'); 249 | } 250 | 251 | #[test] 252 | #[should_panic] 253 | fn write_byte_panics_if_out_of_bounds() { 254 | let mut data = [b'b', b'a', b'r']; 255 | 256 | let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 257 | slice.write_byte(4, b'f'); 258 | } 259 | 260 | #[test] 261 | #[should_panic] 262 | fn copy_from_slice_panics_if_different_length_1() { 263 | let mut data = [b'b', b'a', b'r']; 264 | 265 | let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 266 | slice.copy_from_slice(b"a"); 267 | } 268 | 269 | #[test] 270 | #[should_panic] 271 | fn copy_from_slice_panics_if_different_length_2() { 272 | let mut data = [b'b', b'a', b'r']; 273 | 274 | let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 275 | slice.copy_from_slice(b"abcd"); 276 | } 277 | -------------------------------------------------------------------------------- /tests/test_bytes.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::{Buf, BufMut, Bytes, BytesMut}; 4 | use std::sync::atomic::{AtomicUsize, Ordering}; 5 | use std::sync::Arc; 6 | 7 | use std::panic::{self, AssertUnwindSafe}; 8 | use std::usize; 9 | 10 | const LONG: &[u8] = b"mary had a little lamb, little lamb, little lamb"; 11 | const SHORT: &[u8] = b"hello world"; 12 | 13 | fn is_sync() {} 14 | fn is_send() {} 15 | 16 | #[test] 17 | fn test_bounds() { 18 | is_sync::(); 19 | is_sync::(); 20 | is_send::(); 21 | is_send::(); 22 | } 23 | 24 | #[test] 25 | fn test_layout() { 26 | use std::mem; 27 | 28 | assert_eq!( 29 | mem::size_of::(), 30 | mem::size_of::() * 4, 31 | "Bytes size should be 4 words", 32 | ); 33 | assert_eq!( 34 | mem::size_of::(), 35 | mem::size_of::() * 4, 36 | "BytesMut should be 4 words", 37 | ); 38 | 39 | assert_eq!( 40 | mem::size_of::(), 41 | mem::size_of::>(), 42 | "Bytes should be same size as Option", 43 | ); 44 | 45 | assert_eq!( 46 | mem::size_of::(), 47 | mem::size_of::>(), 48 | "BytesMut should be same size as Option", 49 | ); 50 | } 51 | 52 | #[test] 53 | fn from_slice() { 54 | let a = Bytes::from(&b"abcdefgh"[..]); 55 | assert_eq!(a, b"abcdefgh"[..]); 56 | assert_eq!(a, &b"abcdefgh"[..]); 57 | assert_eq!(a, Vec::from(&b"abcdefgh"[..])); 58 | assert_eq!(b"abcdefgh"[..], a); 59 | assert_eq!(&b"abcdefgh"[..], a); 60 | assert_eq!(Vec::from(&b"abcdefgh"[..]), a); 61 | 62 | let a = BytesMut::from(&b"abcdefgh"[..]); 63 | assert_eq!(a, b"abcdefgh"[..]); 64 | assert_eq!(a, &b"abcdefgh"[..]); 65 | assert_eq!(a, Vec::from(&b"abcdefgh"[..])); 66 | assert_eq!(b"abcdefgh"[..], a); 67 | assert_eq!(&b"abcdefgh"[..], a); 68 | assert_eq!(Vec::from(&b"abcdefgh"[..]), a); 69 | } 70 | 71 | #[test] 72 | fn fmt() { 73 | let a = format!("{:?}", Bytes::from(&b"abcdefg"[..])); 74 | let b = "b\"abcdefg\""; 75 | 76 | assert_eq!(a, b); 77 | 78 | let a = format!("{:?}", BytesMut::from(&b"abcdefg"[..])); 79 | assert_eq!(a, b); 80 | } 81 | 82 | #[test] 83 | fn fmt_write() { 84 | use std::fmt::Write; 85 | use std::iter::FromIterator; 86 | let s = String::from_iter((0..10).map(|_| "abcdefg")); 87 | 88 | let mut a = BytesMut::with_capacity(64); 89 | write!(a, "{}", &s[..64]).unwrap(); 90 | assert_eq!(a, s[..64].as_bytes()); 91 | 92 | let mut b = BytesMut::with_capacity(64); 93 | write!(b, "{}", &s[..32]).unwrap(); 94 | write!(b, "{}", &s[32..64]).unwrap(); 95 | assert_eq!(b, s[..64].as_bytes()); 96 | 97 | let mut c = BytesMut::with_capacity(64); 98 | write!(c, "{}", s).unwrap(); 99 | assert_eq!(c, s[..].as_bytes()); 100 | } 101 | 102 | #[test] 103 | fn len() { 104 | let a = Bytes::from(&b"abcdefg"[..]); 105 | assert_eq!(a.len(), 7); 106 | 107 | let a = BytesMut::from(&b"abcdefg"[..]); 108 | assert_eq!(a.len(), 7); 109 | 110 | let a = Bytes::from(&b""[..]); 111 | assert!(a.is_empty()); 112 | 113 | let a = BytesMut::from(&b""[..]); 114 | assert!(a.is_empty()); 115 | } 116 | 117 | #[test] 118 | fn index() { 119 | let a = Bytes::from(&b"hello world"[..]); 120 | assert_eq!(a[0..5], *b"hello"); 121 | } 122 | 123 | #[test] 124 | fn slice() { 125 | let a = Bytes::from(&b"hello world"[..]); 126 | 127 | let b = a.slice(3..5); 128 | assert_eq!(b, b"lo"[..]); 129 | 130 | let b = a.slice(0..0); 131 | assert_eq!(b, b""[..]); 132 | 133 | let b = a.slice(3..3); 134 | assert_eq!(b, b""[..]); 135 | 136 | let b = a.slice(a.len()..a.len()); 137 | assert_eq!(b, b""[..]); 138 | 139 | let b = a.slice(..5); 140 | assert_eq!(b, b"hello"[..]); 141 | 142 | let b = a.slice(3..); 143 | assert_eq!(b, b"lo world"[..]); 144 | } 145 | 146 | #[test] 147 | #[should_panic] 148 | fn slice_oob_1() { 149 | let a = Bytes::from(&b"hello world"[..]); 150 | a.slice(5..44); 151 | } 152 | 153 | #[test] 154 | #[should_panic] 155 | fn slice_oob_2() { 156 | let a = Bytes::from(&b"hello world"[..]); 157 | a.slice(44..49); 158 | } 159 | 160 | #[test] 161 | #[should_panic] 162 | fn slice_start_greater_than_end() { 163 | let a = Bytes::from(&b"hello world"[..]); 164 | a.slice(5..3); 165 | } 166 | 167 | #[test] 168 | fn split_off() { 169 | let mut hello = Bytes::from(&b"helloworld"[..]); 170 | let world = hello.split_off(5); 171 | 172 | assert_eq!(hello, &b"hello"[..]); 173 | assert_eq!(world, &b"world"[..]); 174 | 175 | let mut hello = BytesMut::from(&b"helloworld"[..]); 176 | let world = hello.split_off(5); 177 | 178 | assert_eq!(hello, &b"hello"[..]); 179 | assert_eq!(world, &b"world"[..]); 180 | } 181 | 182 | #[test] 183 | #[should_panic] 184 | fn split_off_oob() { 185 | let mut hello = Bytes::from(&b"helloworld"[..]); 186 | let _ = hello.split_off(44); 187 | } 188 | 189 | #[test] 190 | #[should_panic = "split_off out of bounds"] 191 | fn bytes_mut_split_off_oob() { 192 | let mut hello = BytesMut::from(&b"helloworld"[..]); 193 | let _ = hello.split_off(44); 194 | } 195 | 196 | #[test] 197 | fn split_off_uninitialized() { 198 | let mut bytes = BytesMut::with_capacity(1024); 199 | let other = bytes.split_off(128); 200 | 201 | assert_eq!(bytes.len(), 0); 202 | assert_eq!(bytes.capacity(), 128); 203 | 204 | assert_eq!(other.len(), 0); 205 | assert_eq!(other.capacity(), 896); 206 | } 207 | 208 | #[test] 209 | fn split_off_to_loop() { 210 | let s = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 211 | 212 | for i in 0..(s.len() + 1) { 213 | { 214 | let mut bytes = Bytes::from(&s[..]); 215 | let off = bytes.split_off(i); 216 | assert_eq!(i, bytes.len()); 217 | let mut sum = Vec::new(); 218 | sum.extend(bytes.iter()); 219 | sum.extend(off.iter()); 220 | assert_eq!(&s[..], &sum[..]); 221 | } 222 | { 223 | let mut bytes = BytesMut::from(&s[..]); 224 | let off = bytes.split_off(i); 225 | assert_eq!(i, bytes.len()); 226 | let mut sum = Vec::new(); 227 | sum.extend(&bytes); 228 | sum.extend(&off); 229 | assert_eq!(&s[..], &sum[..]); 230 | } 231 | { 232 | let mut bytes = Bytes::from(&s[..]); 233 | let off = bytes.split_to(i); 234 | assert_eq!(i, off.len()); 235 | let mut sum = Vec::new(); 236 | sum.extend(off.iter()); 237 | sum.extend(bytes.iter()); 238 | assert_eq!(&s[..], &sum[..]); 239 | } 240 | { 241 | let mut bytes = BytesMut::from(&s[..]); 242 | let off = bytes.split_to(i); 243 | assert_eq!(i, off.len()); 244 | let mut sum = Vec::new(); 245 | sum.extend(&off); 246 | sum.extend(&bytes); 247 | assert_eq!(&s[..], &sum[..]); 248 | } 249 | } 250 | } 251 | 252 | #[test] 253 | fn split_to_1() { 254 | // Static 255 | let mut a = Bytes::from_static(SHORT); 256 | let b = a.split_to(4); 257 | 258 | assert_eq!(SHORT[4..], a); 259 | assert_eq!(SHORT[..4], b); 260 | 261 | // Allocated 262 | let mut a = Bytes::copy_from_slice(LONG); 263 | let b = a.split_to(4); 264 | 265 | assert_eq!(LONG[4..], a); 266 | assert_eq!(LONG[..4], b); 267 | 268 | let mut a = Bytes::copy_from_slice(LONG); 269 | let b = a.split_to(30); 270 | 271 | assert_eq!(LONG[30..], a); 272 | assert_eq!(LONG[..30], b); 273 | } 274 | 275 | #[test] 276 | fn split_to_2() { 277 | let mut a = Bytes::from(LONG); 278 | assert_eq!(LONG, a); 279 | 280 | let b = a.split_to(1); 281 | 282 | assert_eq!(LONG[1..], a); 283 | drop(b); 284 | } 285 | 286 | #[test] 287 | #[should_panic] 288 | fn split_to_oob() { 289 | let mut hello = Bytes::from(&b"helloworld"[..]); 290 | let _ = hello.split_to(33); 291 | } 292 | 293 | #[test] 294 | #[should_panic] 295 | fn split_to_oob_mut() { 296 | let mut hello = BytesMut::from(&b"helloworld"[..]); 297 | let _ = hello.split_to(33); 298 | } 299 | 300 | #[test] 301 | #[should_panic] 302 | fn split_to_uninitialized() { 303 | let mut bytes = BytesMut::with_capacity(1024); 304 | let _other = bytes.split_to(128); 305 | } 306 | 307 | #[test] 308 | #[cfg_attr(not(panic = "unwind"), ignore)] 309 | fn split_off_to_at_gt_len() { 310 | fn make_bytes() -> Bytes { 311 | let mut bytes = BytesMut::with_capacity(100); 312 | bytes.put_slice(&[10, 20, 30, 40]); 313 | bytes.freeze() 314 | } 315 | 316 | use std::panic; 317 | 318 | let _ = make_bytes().split_to(4); 319 | let _ = make_bytes().split_off(4); 320 | 321 | assert!(panic::catch_unwind(move || { 322 | let _ = make_bytes().split_to(5); 323 | }) 324 | .is_err()); 325 | 326 | assert!(panic::catch_unwind(move || { 327 | let _ = make_bytes().split_off(5); 328 | }) 329 | .is_err()); 330 | } 331 | 332 | #[test] 333 | fn truncate() { 334 | let s = &b"helloworld"[..]; 335 | let mut hello = Bytes::from(s); 336 | hello.truncate(15); 337 | assert_eq!(hello, s); 338 | hello.truncate(10); 339 | assert_eq!(hello, s); 340 | hello.truncate(5); 341 | assert_eq!(hello, "hello"); 342 | } 343 | 344 | #[test] 345 | fn freeze_clone_shared() { 346 | let s = &b"abcdefgh"[..]; 347 | let b = BytesMut::from(s).split().freeze(); 348 | assert_eq!(b, s); 349 | let c = b.clone(); 350 | assert_eq!(c, s); 351 | } 352 | 353 | #[test] 354 | fn freeze_clone_unique() { 355 | let s = &b"abcdefgh"[..]; 356 | let b = BytesMut::from(s).freeze(); 357 | assert_eq!(b, s); 358 | let c = b.clone(); 359 | assert_eq!(c, s); 360 | } 361 | 362 | #[test] 363 | fn freeze_after_advance() { 364 | let s = &b"abcdefgh"[..]; 365 | let mut b = BytesMut::from(s); 366 | b.advance(1); 367 | assert_eq!(b, s[1..]); 368 | let b = b.freeze(); 369 | // Verify fix for #352. Previously, freeze would ignore the start offset 370 | // for BytesMuts in Vec mode. 371 | assert_eq!(b, s[1..]); 372 | } 373 | 374 | #[test] 375 | fn freeze_after_advance_arc() { 376 | let s = &b"abcdefgh"[..]; 377 | let mut b = BytesMut::from(s); 378 | // Make b Arc 379 | let _ = b.split_to(0); 380 | b.advance(1); 381 | assert_eq!(b, s[1..]); 382 | let b = b.freeze(); 383 | assert_eq!(b, s[1..]); 384 | } 385 | 386 | #[test] 387 | fn freeze_after_split_to() { 388 | let s = &b"abcdefgh"[..]; 389 | let mut b = BytesMut::from(s); 390 | let _ = b.split_to(1); 391 | assert_eq!(b, s[1..]); 392 | let b = b.freeze(); 393 | assert_eq!(b, s[1..]); 394 | } 395 | 396 | #[test] 397 | fn freeze_after_truncate() { 398 | let s = &b"abcdefgh"[..]; 399 | let mut b = BytesMut::from(s); 400 | b.truncate(7); 401 | assert_eq!(b, s[..7]); 402 | let b = b.freeze(); 403 | assert_eq!(b, s[..7]); 404 | } 405 | 406 | #[test] 407 | fn freeze_after_truncate_arc() { 408 | let s = &b"abcdefgh"[..]; 409 | let mut b = BytesMut::from(s); 410 | // Make b Arc 411 | let _ = b.split_to(0); 412 | b.truncate(7); 413 | assert_eq!(b, s[..7]); 414 | let b = b.freeze(); 415 | assert_eq!(b, s[..7]); 416 | } 417 | 418 | #[test] 419 | fn freeze_after_split_off() { 420 | let s = &b"abcdefgh"[..]; 421 | let mut b = BytesMut::from(s); 422 | let _ = b.split_off(7); 423 | assert_eq!(b, s[..7]); 424 | let b = b.freeze(); 425 | assert_eq!(b, s[..7]); 426 | } 427 | 428 | #[test] 429 | fn fns_defined_for_bytes_mut() { 430 | let mut bytes = BytesMut::from(&b"hello world"[..]); 431 | 432 | let _ = bytes.as_ptr(); 433 | let _ = bytes.as_mut_ptr(); 434 | 435 | // Iterator 436 | let v: Vec = bytes.as_ref().iter().cloned().collect(); 437 | assert_eq!(&v[..], bytes); 438 | } 439 | 440 | #[test] 441 | fn reserve_convert() { 442 | // Vec -> Vec 443 | let mut bytes = BytesMut::from(LONG); 444 | bytes.reserve(64); 445 | assert_eq!(bytes.capacity(), LONG.len() + 64); 446 | 447 | // Arc -> Vec 448 | let mut bytes = BytesMut::from(LONG); 449 | let a = bytes.split_to(30); 450 | 451 | bytes.reserve(128); 452 | assert!(bytes.capacity() >= bytes.len() + 128); 453 | 454 | drop(a); 455 | } 456 | 457 | #[test] 458 | fn reserve_growth() { 459 | let mut bytes = BytesMut::with_capacity(64); 460 | bytes.put("hello world".as_bytes()); 461 | let _ = bytes.split(); 462 | 463 | bytes.reserve(65); 464 | assert_eq!(bytes.capacity(), 117); 465 | } 466 | 467 | #[test] 468 | fn reserve_allocates_at_least_original_capacity() { 469 | let mut bytes = BytesMut::with_capacity(1024); 470 | 471 | for i in 0..1020 { 472 | bytes.put_u8(i as u8); 473 | } 474 | 475 | let _other = bytes.split(); 476 | 477 | bytes.reserve(16); 478 | assert_eq!(bytes.capacity(), 1024); 479 | } 480 | 481 | #[test] 482 | #[cfg_attr(miri, ignore)] // Miri is too slow 483 | fn reserve_max_original_capacity_value() { 484 | const SIZE: usize = 128 * 1024; 485 | 486 | let mut bytes = BytesMut::with_capacity(SIZE); 487 | 488 | for _ in 0..SIZE { 489 | bytes.put_u8(0u8); 490 | } 491 | 492 | let _other = bytes.split(); 493 | 494 | bytes.reserve(16); 495 | assert_eq!(bytes.capacity(), 64 * 1024); 496 | } 497 | 498 | #[test] 499 | fn reserve_vec_recycling() { 500 | let mut bytes = BytesMut::with_capacity(16); 501 | assert_eq!(bytes.capacity(), 16); 502 | let addr = bytes.as_ptr() as usize; 503 | bytes.put("0123456789012345".as_bytes()); 504 | assert_eq!(bytes.as_ptr() as usize, addr); 505 | bytes.advance(10); 506 | assert_eq!(bytes.capacity(), 6); 507 | bytes.reserve(8); 508 | assert_eq!(bytes.capacity(), 16); 509 | assert_eq!(bytes.as_ptr() as usize, addr); 510 | } 511 | 512 | #[test] 513 | fn reserve_in_arc_unique_does_not_overallocate() { 514 | let mut bytes = BytesMut::with_capacity(1000); 515 | let _ = bytes.split(); 516 | 517 | // now bytes is Arc and refcount == 1 518 | 519 | assert_eq!(1000, bytes.capacity()); 520 | bytes.reserve(2001); 521 | assert_eq!(2001, bytes.capacity()); 522 | } 523 | 524 | #[test] 525 | fn reserve_in_arc_unique_doubles() { 526 | let mut bytes = BytesMut::with_capacity(1000); 527 | let _ = bytes.split(); 528 | 529 | // now bytes is Arc and refcount == 1 530 | 531 | assert_eq!(1000, bytes.capacity()); 532 | bytes.reserve(1001); 533 | assert_eq!(2000, bytes.capacity()); 534 | } 535 | 536 | #[test] 537 | fn reserve_in_arc_unique_does_not_overallocate_after_split() { 538 | let mut bytes = BytesMut::from(LONG); 539 | let orig_capacity = bytes.capacity(); 540 | drop(bytes.split_off(LONG.len() / 2)); 541 | 542 | // now bytes is Arc and refcount == 1 543 | 544 | let new_capacity = bytes.capacity(); 545 | bytes.reserve(orig_capacity - new_capacity); 546 | assert_eq!(bytes.capacity(), orig_capacity); 547 | } 548 | 549 | #[test] 550 | fn reserve_in_arc_unique_does_not_overallocate_after_multiple_splits() { 551 | let mut bytes = BytesMut::from(LONG); 552 | let orig_capacity = bytes.capacity(); 553 | for _ in 0..10 { 554 | drop(bytes.split_off(LONG.len() / 2)); 555 | 556 | // now bytes is Arc and refcount == 1 557 | 558 | let new_capacity = bytes.capacity(); 559 | bytes.reserve(orig_capacity - new_capacity); 560 | } 561 | assert_eq!(bytes.capacity(), orig_capacity); 562 | } 563 | 564 | #[test] 565 | fn reserve_in_arc_nonunique_does_not_overallocate() { 566 | let mut bytes = BytesMut::with_capacity(1000); 567 | let _copy = bytes.split(); 568 | 569 | // now bytes is Arc and refcount == 2 570 | 571 | assert_eq!(1000, bytes.capacity()); 572 | bytes.reserve(2001); 573 | assert_eq!(2001, bytes.capacity()); 574 | } 575 | 576 | /// This function tests `BytesMut::reserve_inner`, where `BytesMut` holds 577 | /// a unique reference to the shared vector and decide to reuse it 578 | /// by reallocating the `Vec`. 579 | #[test] 580 | fn reserve_shared_reuse() { 581 | let mut bytes = BytesMut::with_capacity(1000); 582 | bytes.put_slice(b"Hello, World!"); 583 | drop(bytes.split()); 584 | 585 | bytes.put_slice(b"!123ex123,sadchELLO,_wORLD!"); 586 | // Use split_off so that v.capacity() - self.cap != off 587 | drop(bytes.split_off(9)); 588 | assert_eq!(&*bytes, b"!123ex123"); 589 | 590 | bytes.reserve(2000); 591 | assert_eq!(&*bytes, b"!123ex123"); 592 | assert_eq!(bytes.capacity(), 2009); 593 | } 594 | 595 | #[test] 596 | fn extend_mut() { 597 | let mut bytes = BytesMut::with_capacity(0); 598 | bytes.extend(LONG); 599 | assert_eq!(*bytes, LONG[..]); 600 | } 601 | 602 | #[test] 603 | fn extend_from_slice_mut() { 604 | for &i in &[3, 34] { 605 | let mut bytes = BytesMut::new(); 606 | bytes.extend_from_slice(&LONG[..i]); 607 | bytes.extend_from_slice(&LONG[i..]); 608 | assert_eq!(LONG[..], *bytes); 609 | } 610 | } 611 | 612 | #[test] 613 | fn extend_mut_from_bytes() { 614 | let mut bytes = BytesMut::with_capacity(0); 615 | bytes.extend([Bytes::from(LONG)]); 616 | assert_eq!(*bytes, LONG[..]); 617 | } 618 | 619 | #[test] 620 | fn extend_past_lower_limit_of_size_hint() { 621 | // See https://github.com/tokio-rs/bytes/pull/674#pullrequestreview-1913035700 622 | struct Iter(I); 623 | 624 | impl> Iterator for Iter { 625 | type Item = u8; 626 | 627 | fn next(&mut self) -> Option { 628 | self.0.next() 629 | } 630 | 631 | fn size_hint(&self) -> (usize, Option) { 632 | (5, None) 633 | } 634 | } 635 | 636 | let mut bytes = BytesMut::with_capacity(5); 637 | bytes.extend(Iter(std::iter::repeat(0).take(10))); 638 | assert_eq!(bytes.len(), 10); 639 | } 640 | 641 | #[test] 642 | fn extend_mut_without_size_hint() { 643 | let mut bytes = BytesMut::with_capacity(0); 644 | let mut long_iter = LONG.iter(); 645 | 646 | // Use iter::from_fn since it doesn't know a size_hint 647 | bytes.extend(std::iter::from_fn(|| long_iter.next())); 648 | assert_eq!(*bytes, LONG[..]); 649 | } 650 | 651 | #[test] 652 | fn from_static() { 653 | let mut a = Bytes::from_static(b"ab"); 654 | let b = a.split_off(1); 655 | 656 | assert_eq!(a, b"a"[..]); 657 | assert_eq!(b, b"b"[..]); 658 | } 659 | 660 | #[test] 661 | fn advance_static() { 662 | let mut a = Bytes::from_static(b"hello world"); 663 | a.advance(6); 664 | assert_eq!(a, &b"world"[..]); 665 | } 666 | 667 | #[test] 668 | fn advance_vec() { 669 | let mut a = Bytes::from(b"hello world boooo yah world zomg wat wat".to_vec()); 670 | a.advance(16); 671 | assert_eq!(a, b"o yah world zomg wat wat"[..]); 672 | 673 | a.advance(4); 674 | assert_eq!(a, b"h world zomg wat wat"[..]); 675 | 676 | a.advance(6); 677 | assert_eq!(a, b"d zomg wat wat"[..]); 678 | } 679 | 680 | #[test] 681 | fn advance_bytes_mut() { 682 | let mut a = BytesMut::from("hello world boooo yah world zomg wat wat"); 683 | a.advance(16); 684 | assert_eq!(a, b"o yah world zomg wat wat"[..]); 685 | 686 | a.advance(4); 687 | assert_eq!(a, b"h world zomg wat wat"[..]); 688 | 689 | // Reserve some space. 690 | a.reserve(1024); 691 | assert_eq!(a, b"h world zomg wat wat"[..]); 692 | 693 | a.advance(6); 694 | assert_eq!(a, b"d zomg wat wat"[..]); 695 | } 696 | 697 | // Ensures BytesMut::advance reduces always capacity 698 | // 699 | // See https://github.com/tokio-rs/bytes/issues/725 700 | #[test] 701 | fn advance_bytes_mut_remaining_capacity() { 702 | // reduce the search space under miri 703 | let max_capacity = if cfg!(miri) { 16 } else { 256 }; 704 | for capacity in 0..=max_capacity { 705 | for len in 0..=capacity { 706 | for advance in 0..=len { 707 | eprintln!("testing capacity={capacity}, len={len}, advance={advance}"); 708 | let mut buf = BytesMut::with_capacity(capacity); 709 | 710 | buf.resize(len, 42); 711 | assert_eq!(buf.len(), len, "resize should write `len` bytes"); 712 | assert_eq!( 713 | buf.remaining(), 714 | len, 715 | "Buf::remaining() should equal BytesMut::len" 716 | ); 717 | 718 | buf.advance(advance); 719 | assert_eq!( 720 | buf.remaining(), 721 | len - advance, 722 | "Buf::advance should reduce the remaining len" 723 | ); 724 | assert_eq!( 725 | buf.capacity(), 726 | capacity - advance, 727 | "Buf::advance should reduce the remaining capacity" 728 | ); 729 | } 730 | } 731 | } 732 | } 733 | 734 | #[test] 735 | #[should_panic] 736 | fn advance_past_len() { 737 | let mut a = BytesMut::from("hello world"); 738 | a.advance(20); 739 | } 740 | 741 | #[test] 742 | #[should_panic] 743 | fn mut_advance_past_len() { 744 | let mut a = BytesMut::from("hello world"); 745 | unsafe { 746 | a.advance_mut(20); 747 | } 748 | } 749 | 750 | #[test] 751 | // Only run these tests on little endian systems. CI uses qemu for testing 752 | // big endian... and qemu doesn't really support threading all that well. 753 | #[cfg(any(miri, target_endian = "little"))] 754 | #[cfg(not(target_family = "wasm"))] // wasm without experimental threads proposal doesn't support threads 755 | fn stress() { 756 | // Tests promoting a buffer from a vec -> shared in a concurrent situation 757 | use std::sync::{Arc, Barrier}; 758 | use std::thread; 759 | 760 | const THREADS: usize = 8; 761 | const ITERS: usize = if cfg!(miri) { 100 } else { 1_000 }; 762 | 763 | for i in 0..ITERS { 764 | let data = [i as u8; 256]; 765 | let buf = Arc::new(Bytes::copy_from_slice(&data[..])); 766 | 767 | let barrier = Arc::new(Barrier::new(THREADS)); 768 | let mut joins = Vec::with_capacity(THREADS); 769 | 770 | for _ in 0..THREADS { 771 | let c = barrier.clone(); 772 | let buf = buf.clone(); 773 | 774 | joins.push(thread::spawn(move || { 775 | c.wait(); 776 | let buf: Bytes = (*buf).clone(); 777 | drop(buf); 778 | })); 779 | } 780 | 781 | for th in joins { 782 | th.join().unwrap(); 783 | } 784 | 785 | assert_eq!(*buf, data[..]); 786 | } 787 | } 788 | 789 | #[test] 790 | fn partial_eq_bytesmut() { 791 | let bytes = Bytes::from(&b"The quick red fox"[..]); 792 | let bytesmut = BytesMut::from(&b"The quick red fox"[..]); 793 | assert!(bytes == bytesmut); 794 | assert!(bytesmut == bytes); 795 | let bytes2 = Bytes::from(&b"Jumped over the lazy brown dog"[..]); 796 | assert!(bytes2 != bytesmut); 797 | assert!(bytesmut != bytes2); 798 | } 799 | 800 | #[test] 801 | fn bytes_mut_unsplit_basic() { 802 | let mut buf = BytesMut::with_capacity(64); 803 | buf.extend_from_slice(b"aaabbbcccddd"); 804 | 805 | let splitted = buf.split_off(6); 806 | assert_eq!(b"aaabbb", &buf[..]); 807 | assert_eq!(b"cccddd", &splitted[..]); 808 | 809 | buf.unsplit(splitted); 810 | assert_eq!(b"aaabbbcccddd", &buf[..]); 811 | } 812 | 813 | #[test] 814 | fn bytes_mut_unsplit_empty_other() { 815 | let mut buf = BytesMut::with_capacity(64); 816 | buf.extend_from_slice(b"aaabbbcccddd"); 817 | 818 | // empty other 819 | let other = BytesMut::new(); 820 | 821 | buf.unsplit(other); 822 | assert_eq!(b"aaabbbcccddd", &buf[..]); 823 | } 824 | 825 | #[test] 826 | fn bytes_mut_unsplit_empty_self() { 827 | // empty self 828 | let mut buf = BytesMut::new(); 829 | 830 | let mut other = BytesMut::with_capacity(64); 831 | other.extend_from_slice(b"aaabbbcccddd"); 832 | 833 | buf.unsplit(other); 834 | assert_eq!(b"aaabbbcccddd", &buf[..]); 835 | } 836 | 837 | #[test] 838 | fn bytes_mut_unsplit_other_keeps_capacity() { 839 | let mut buf = BytesMut::with_capacity(64); 840 | buf.extend_from_slice(b"aabb"); 841 | 842 | // non empty other created "from" buf 843 | let mut other = buf.split_off(buf.len()); 844 | other.extend_from_slice(b"ccddee"); 845 | buf.unsplit(other); 846 | 847 | assert_eq!(buf.capacity(), 64); 848 | } 849 | 850 | #[test] 851 | fn bytes_mut_unsplit_empty_other_keeps_capacity() { 852 | let mut buf = BytesMut::with_capacity(64); 853 | buf.extend_from_slice(b"aabbccddee"); 854 | 855 | // empty other created "from" buf 856 | let other = buf.split_off(buf.len()); 857 | buf.unsplit(other); 858 | 859 | assert_eq!(buf.capacity(), 64); 860 | } 861 | 862 | #[test] 863 | fn bytes_mut_unsplit_arc_different() { 864 | let mut buf = BytesMut::with_capacity(64); 865 | buf.extend_from_slice(b"aaaabbbbeeee"); 866 | 867 | let _ = buf.split_off(8); //arc 868 | 869 | let mut buf2 = BytesMut::with_capacity(64); 870 | buf2.extend_from_slice(b"ccccddddeeee"); 871 | 872 | let _ = buf2.split_off(8); //arc 873 | 874 | buf.unsplit(buf2); 875 | assert_eq!(b"aaaabbbbccccdddd", &buf[..]); 876 | } 877 | 878 | #[test] 879 | fn bytes_mut_unsplit_arc_non_contiguous() { 880 | let mut buf = BytesMut::with_capacity(64); 881 | buf.extend_from_slice(b"aaaabbbbeeeeccccdddd"); 882 | 883 | let mut buf2 = buf.split_off(8); //arc 884 | 885 | let buf3 = buf2.split_off(4); //arc 886 | 887 | buf.unsplit(buf3); 888 | assert_eq!(b"aaaabbbbccccdddd", &buf[..]); 889 | } 890 | 891 | #[test] 892 | fn bytes_mut_unsplit_two_split_offs() { 893 | let mut buf = BytesMut::with_capacity(64); 894 | buf.extend_from_slice(b"aaaabbbbccccdddd"); 895 | 896 | let mut buf2 = buf.split_off(8); //arc 897 | let buf3 = buf2.split_off(4); //arc 898 | 899 | buf2.unsplit(buf3); 900 | buf.unsplit(buf2); 901 | assert_eq!(b"aaaabbbbccccdddd", &buf[..]); 902 | } 903 | 904 | #[test] 905 | fn from_iter_no_size_hint() { 906 | use std::iter; 907 | 908 | let mut expect = vec![]; 909 | 910 | let actual: Bytes = iter::repeat(b'x') 911 | .scan(100, |cnt, item| { 912 | if *cnt >= 1 { 913 | *cnt -= 1; 914 | expect.push(item); 915 | Some(item) 916 | } else { 917 | None 918 | } 919 | }) 920 | .collect(); 921 | 922 | assert_eq!(&actual[..], &expect[..]); 923 | } 924 | 925 | fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) { 926 | let slice = &(bytes.as_ref()[start..end]); 927 | let sub = bytes.slice_ref(slice); 928 | assert_eq!(&sub[..], expected); 929 | } 930 | 931 | #[test] 932 | fn slice_ref_works() { 933 | let bytes = Bytes::from(&b"012345678"[..]); 934 | 935 | test_slice_ref(&bytes, 0, 0, b""); 936 | test_slice_ref(&bytes, 0, 3, b"012"); 937 | test_slice_ref(&bytes, 2, 6, b"2345"); 938 | test_slice_ref(&bytes, 7, 9, b"78"); 939 | test_slice_ref(&bytes, 9, 9, b""); 940 | } 941 | 942 | #[test] 943 | fn slice_ref_empty() { 944 | let bytes = Bytes::from(&b""[..]); 945 | let slice = &(bytes.as_ref()[0..0]); 946 | 947 | let sub = bytes.slice_ref(slice); 948 | assert_eq!(&sub[..], b""); 949 | } 950 | 951 | #[test] 952 | fn slice_ref_empty_subslice() { 953 | let bytes = Bytes::from(&b"abcde"[..]); 954 | let subbytes = bytes.slice(0..0); 955 | let slice = &subbytes[..]; 956 | // The `slice` object is derived from the original `bytes` object 957 | // so `slice_ref` should work. 958 | assert_eq!(Bytes::new(), bytes.slice_ref(slice)); 959 | } 960 | 961 | #[test] 962 | #[should_panic] 963 | fn slice_ref_catches_not_a_subset() { 964 | let bytes = Bytes::from(&b"012345678"[..]); 965 | let slice = &b"012345"[0..4]; 966 | 967 | bytes.slice_ref(slice); 968 | } 969 | 970 | #[test] 971 | fn slice_ref_not_an_empty_subset() { 972 | let bytes = Bytes::from(&b"012345678"[..]); 973 | let slice = &b""[0..0]; 974 | 975 | assert_eq!(Bytes::new(), bytes.slice_ref(slice)); 976 | } 977 | 978 | #[test] 979 | fn empty_slice_ref_not_an_empty_subset() { 980 | let bytes = Bytes::new(); 981 | let slice = &b"some other slice"[0..0]; 982 | 983 | assert_eq!(Bytes::new(), bytes.slice_ref(slice)); 984 | } 985 | 986 | #[test] 987 | fn bytes_buf_mut_advance() { 988 | let mut bytes = BytesMut::with_capacity(1024); 989 | 990 | unsafe { 991 | let ptr = bytes.chunk_mut().as_mut_ptr(); 992 | assert_eq!(1024, bytes.chunk_mut().len()); 993 | 994 | bytes.advance_mut(10); 995 | 996 | let next = bytes.chunk_mut().as_mut_ptr(); 997 | assert_eq!(1024 - 10, bytes.chunk_mut().len()); 998 | assert_eq!(ptr.offset(10), next); 999 | 1000 | // advance to the end 1001 | bytes.advance_mut(1024 - 10); 1002 | 1003 | // The buffer size is doubled 1004 | assert_eq!(1024, bytes.chunk_mut().len()); 1005 | } 1006 | } 1007 | 1008 | #[test] 1009 | fn bytes_buf_mut_reuse_when_fully_consumed() { 1010 | use bytes::{Buf, BytesMut}; 1011 | let mut buf = BytesMut::new(); 1012 | buf.reserve(8192); 1013 | buf.extend_from_slice(&[0u8; 100][..]); 1014 | 1015 | let p = &buf[0] as *const u8; 1016 | buf.advance(100); 1017 | 1018 | buf.reserve(8192); 1019 | buf.extend_from_slice(b" "); 1020 | 1021 | assert_eq!(&buf[0] as *const u8, p); 1022 | } 1023 | 1024 | #[test] 1025 | #[should_panic] 1026 | fn bytes_reserve_overflow() { 1027 | let mut bytes = BytesMut::with_capacity(1024); 1028 | bytes.put_slice(b"hello world"); 1029 | 1030 | bytes.reserve(usize::MAX); 1031 | } 1032 | 1033 | #[test] 1034 | fn bytes_with_capacity_but_empty() { 1035 | // See https://github.com/tokio-rs/bytes/issues/340 1036 | let vec = Vec::with_capacity(1); 1037 | let _ = Bytes::from(vec); 1038 | } 1039 | 1040 | #[test] 1041 | fn bytes_put_bytes() { 1042 | let mut bytes = BytesMut::new(); 1043 | bytes.put_u8(17); 1044 | bytes.put_bytes(19, 2); 1045 | assert_eq!([17, 19, 19], bytes.as_ref()); 1046 | } 1047 | 1048 | #[test] 1049 | fn box_slice_empty() { 1050 | // See https://github.com/tokio-rs/bytes/issues/340 1051 | let empty: Box<[u8]> = Default::default(); 1052 | let b = Bytes::from(empty); 1053 | assert!(b.is_empty()); 1054 | } 1055 | 1056 | #[test] 1057 | fn bytes_into_vec() { 1058 | // Test kind == KIND_VEC 1059 | let content = b"helloworld"; 1060 | 1061 | let mut bytes = BytesMut::new(); 1062 | bytes.put_slice(content); 1063 | 1064 | let vec: Vec = bytes.into(); 1065 | assert_eq!(&vec, content); 1066 | 1067 | // Test kind == KIND_ARC, shared.is_unique() == True 1068 | let mut bytes = BytesMut::new(); 1069 | bytes.put_slice(b"abcdewe23"); 1070 | bytes.put_slice(content); 1071 | 1072 | // Overwrite the bytes to make sure only one reference to the underlying 1073 | // Vec exists. 1074 | bytes = bytes.split_off(9); 1075 | 1076 | let vec: Vec = bytes.into(); 1077 | assert_eq!(&vec, content); 1078 | 1079 | // Test kind == KIND_ARC, shared.is_unique() == False 1080 | let prefix = b"abcdewe23"; 1081 | 1082 | let mut bytes = BytesMut::new(); 1083 | bytes.put_slice(prefix); 1084 | bytes.put_slice(content); 1085 | 1086 | let vec: Vec = bytes.split_off(prefix.len()).into(); 1087 | assert_eq!(&vec, content); 1088 | 1089 | let vec: Vec = bytes.into(); 1090 | assert_eq!(&vec, prefix); 1091 | } 1092 | 1093 | #[test] 1094 | fn test_bytes_into_vec() { 1095 | // Test STATIC_VTABLE.to_vec 1096 | let bs = b"1b23exfcz3r"; 1097 | let vec: Vec = Bytes::from_static(bs).into(); 1098 | assert_eq!(&*vec, bs); 1099 | 1100 | // Test bytes_mut.SHARED_VTABLE.to_vec impl 1101 | eprintln!("1"); 1102 | let mut bytes_mut: BytesMut = bs[..].into(); 1103 | 1104 | // Set kind to KIND_ARC so that after freeze, Bytes will use bytes_mut.SHARED_VTABLE 1105 | eprintln!("2"); 1106 | drop(bytes_mut.split_off(bs.len())); 1107 | 1108 | eprintln!("3"); 1109 | let b1 = bytes_mut.freeze(); 1110 | eprintln!("4"); 1111 | let b2 = b1.clone(); 1112 | 1113 | eprintln!("{:#?}", (&*b1).as_ptr()); 1114 | 1115 | // shared.is_unique() = False 1116 | eprintln!("5"); 1117 | assert_eq!(&*Vec::from(b2), bs); 1118 | 1119 | // shared.is_unique() = True 1120 | eprintln!("6"); 1121 | assert_eq!(&*Vec::from(b1), bs); 1122 | 1123 | // Test bytes_mut.SHARED_VTABLE.to_vec impl where offset != 0 1124 | let mut bytes_mut1: BytesMut = bs[..].into(); 1125 | let bytes_mut2 = bytes_mut1.split_off(9); 1126 | 1127 | let b1 = bytes_mut1.freeze(); 1128 | let b2 = bytes_mut2.freeze(); 1129 | 1130 | assert_eq!(Vec::from(b2), bs[9..]); 1131 | assert_eq!(Vec::from(b1), bs[..9]); 1132 | } 1133 | 1134 | #[test] 1135 | fn test_bytes_into_vec_promotable_even() { 1136 | let vec = vec![33u8; 1024]; 1137 | 1138 | // Test cases where kind == KIND_VEC 1139 | let b1 = Bytes::from(vec.clone()); 1140 | assert_eq!(Vec::from(b1), vec); 1141 | 1142 | // Test cases where kind == KIND_ARC, ref_cnt == 1 1143 | let b1 = Bytes::from(vec.clone()); 1144 | drop(b1.clone()); 1145 | assert_eq!(Vec::from(b1), vec); 1146 | 1147 | // Test cases where kind == KIND_ARC, ref_cnt == 2 1148 | let b1 = Bytes::from(vec.clone()); 1149 | let b2 = b1.clone(); 1150 | assert_eq!(Vec::from(b1), vec); 1151 | 1152 | // Test cases where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 1153 | assert_eq!(Vec::from(b2), vec); 1154 | 1155 | // Test cases where offset != 0 1156 | let mut b1 = Bytes::from(vec.clone()); 1157 | let b2 = b1.split_off(20); 1158 | 1159 | assert_eq!(Vec::from(b2), vec[20..]); 1160 | assert_eq!(Vec::from(b1), vec[..20]); 1161 | } 1162 | 1163 | #[test] 1164 | fn test_bytes_vec_conversion() { 1165 | let mut vec = Vec::with_capacity(10); 1166 | vec.extend(b"abcdefg"); 1167 | let b = Bytes::from(vec); 1168 | let v = Vec::from(b); 1169 | assert_eq!(v.len(), 7); 1170 | assert_eq!(v.capacity(), 10); 1171 | 1172 | let mut b = Bytes::from(v); 1173 | b.advance(1); 1174 | let v = Vec::from(b); 1175 | assert_eq!(v.len(), 6); 1176 | assert_eq!(v.capacity(), 10); 1177 | assert_eq!(v.as_slice(), b"bcdefg"); 1178 | } 1179 | 1180 | #[test] 1181 | fn test_bytes_mut_conversion() { 1182 | let mut b1 = BytesMut::with_capacity(10); 1183 | b1.extend(b"abcdefg"); 1184 | let b2 = Bytes::from(b1); 1185 | let v = Vec::from(b2); 1186 | assert_eq!(v.len(), 7); 1187 | assert_eq!(v.capacity(), 10); 1188 | 1189 | let mut b = Bytes::from(v); 1190 | b.advance(1); 1191 | let v = Vec::from(b); 1192 | assert_eq!(v.len(), 6); 1193 | assert_eq!(v.capacity(), 10); 1194 | assert_eq!(v.as_slice(), b"bcdefg"); 1195 | } 1196 | 1197 | #[test] 1198 | fn test_bytes_capacity_len() { 1199 | for cap in 0..100 { 1200 | for len in 0..=cap { 1201 | let mut v = Vec::with_capacity(cap); 1202 | v.resize(len, 0); 1203 | let _ = Bytes::from(v); 1204 | } 1205 | } 1206 | } 1207 | 1208 | #[test] 1209 | fn static_is_unique() { 1210 | let b = Bytes::from_static(LONG); 1211 | assert!(!b.is_unique()); 1212 | } 1213 | 1214 | #[test] 1215 | fn vec_is_unique() { 1216 | let v: Vec = LONG.to_vec(); 1217 | let b = Bytes::from(v); 1218 | assert!(b.is_unique()); 1219 | } 1220 | 1221 | #[test] 1222 | fn arc_is_unique() { 1223 | let v: Vec = LONG.to_vec(); 1224 | let b = Bytes::from(v); 1225 | let c = b.clone(); 1226 | assert!(!b.is_unique()); 1227 | drop(c); 1228 | assert!(b.is_unique()); 1229 | } 1230 | 1231 | #[test] 1232 | fn shared_is_unique() { 1233 | let v: Vec = LONG.to_vec(); 1234 | let b = Bytes::from(v); 1235 | let c = b.clone(); 1236 | assert!(!c.is_unique()); 1237 | drop(b); 1238 | assert!(c.is_unique()); 1239 | } 1240 | 1241 | #[test] 1242 | fn mut_shared_is_unique() { 1243 | let mut b = BytesMut::from(LONG); 1244 | let c = b.split().freeze(); 1245 | assert!(!c.is_unique()); 1246 | drop(b); 1247 | assert!(c.is_unique()); 1248 | } 1249 | 1250 | #[test] 1251 | fn test_bytesmut_from_bytes_static() { 1252 | let bs = b"1b23exfcz3r"; 1253 | 1254 | // Test STATIC_VTABLE.to_mut 1255 | let bytes_mut = BytesMut::from(Bytes::from_static(bs)); 1256 | assert_eq!(bytes_mut, bs[..]); 1257 | } 1258 | 1259 | #[test] 1260 | fn test_bytesmut_from_bytes_bytes_mut_vec() { 1261 | let bs = b"1b23exfcz3r"; 1262 | let bs_long = b"1b23exfcz3r1b23exfcz3r"; 1263 | 1264 | // Test case where kind == KIND_VEC 1265 | let mut bytes_mut: BytesMut = bs[..].into(); 1266 | bytes_mut = BytesMut::from(bytes_mut.freeze()); 1267 | assert_eq!(bytes_mut, bs[..]); 1268 | bytes_mut.extend_from_slice(&bs[..]); 1269 | assert_eq!(bytes_mut, bs_long[..]); 1270 | } 1271 | 1272 | #[test] 1273 | fn test_bytesmut_from_bytes_bytes_mut_shared() { 1274 | let bs = b"1b23exfcz3r"; 1275 | 1276 | // Set kind to KIND_ARC so that after freeze, Bytes will use bytes_mut.SHARED_VTABLE 1277 | let mut bytes_mut: BytesMut = bs[..].into(); 1278 | drop(bytes_mut.split_off(bs.len())); 1279 | 1280 | let b1 = bytes_mut.freeze(); 1281 | let b2 = b1.clone(); 1282 | 1283 | // shared.is_unique() = False 1284 | let mut b1m = BytesMut::from(b1); 1285 | assert_eq!(b1m, bs[..]); 1286 | b1m[0] = b'9'; 1287 | 1288 | // shared.is_unique() = True 1289 | let b2m = BytesMut::from(b2); 1290 | assert_eq!(b2m, bs[..]); 1291 | } 1292 | 1293 | #[test] 1294 | fn test_bytesmut_from_bytes_bytes_mut_offset() { 1295 | let bs = b"1b23exfcz3r"; 1296 | 1297 | // Test bytes_mut.SHARED_VTABLE.to_mut impl where offset != 0 1298 | let mut bytes_mut1: BytesMut = bs[..].into(); 1299 | let bytes_mut2 = bytes_mut1.split_off(9); 1300 | 1301 | let b1 = bytes_mut1.freeze(); 1302 | let b2 = bytes_mut2.freeze(); 1303 | 1304 | let b1m = BytesMut::from(b1); 1305 | let b2m = BytesMut::from(b2); 1306 | 1307 | assert_eq!(b2m, bs[9..]); 1308 | assert_eq!(b1m, bs[..9]); 1309 | } 1310 | 1311 | #[test] 1312 | fn test_bytesmut_from_bytes_promotable_even_vec() { 1313 | let vec = vec![33u8; 1024]; 1314 | 1315 | // Test case where kind == KIND_VEC 1316 | let b1 = Bytes::from(vec.clone()); 1317 | let b1m = BytesMut::from(b1); 1318 | assert_eq!(b1m, vec); 1319 | } 1320 | 1321 | #[test] 1322 | fn test_bytesmut_from_bytes_promotable_even_arc_1() { 1323 | let vec = vec![33u8; 1024]; 1324 | 1325 | // Test case where kind == KIND_ARC, ref_cnt == 1 1326 | let b1 = Bytes::from(vec.clone()); 1327 | drop(b1.clone()); 1328 | let b1m = BytesMut::from(b1); 1329 | assert_eq!(b1m, vec); 1330 | } 1331 | 1332 | #[test] 1333 | fn test_bytesmut_from_bytes_promotable_even_arc_2() { 1334 | let vec = vec![33u8; 1024]; 1335 | 1336 | // Test case where kind == KIND_ARC, ref_cnt == 2 1337 | let b1 = Bytes::from(vec.clone()); 1338 | let b2 = b1.clone(); 1339 | let b1m = BytesMut::from(b1); 1340 | assert_eq!(b1m, vec); 1341 | 1342 | // Test case where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 1343 | let b2m = BytesMut::from(b2); 1344 | assert_eq!(b2m, vec); 1345 | } 1346 | 1347 | #[test] 1348 | fn test_bytesmut_from_bytes_promotable_even_arc_offset() { 1349 | let vec = vec![33u8; 1024]; 1350 | 1351 | // Test case where offset != 0 1352 | let mut b1 = Bytes::from(vec.clone()); 1353 | let b2 = b1.split_off(20); 1354 | let b1m = BytesMut::from(b1); 1355 | let b2m = BytesMut::from(b2); 1356 | 1357 | assert_eq!(b2m, vec[20..]); 1358 | assert_eq!(b1m, vec[..20]); 1359 | } 1360 | 1361 | #[test] 1362 | fn try_reclaim_empty() { 1363 | let mut buf = BytesMut::new(); 1364 | assert_eq!(false, buf.try_reclaim(6)); 1365 | buf.reserve(6); 1366 | assert_eq!(true, buf.try_reclaim(6)); 1367 | let cap = buf.capacity(); 1368 | assert!(cap >= 6); 1369 | assert_eq!(false, buf.try_reclaim(cap + 1)); 1370 | 1371 | let mut buf = BytesMut::new(); 1372 | buf.reserve(6); 1373 | let cap = buf.capacity(); 1374 | assert!(cap >= 6); 1375 | let mut split = buf.split(); 1376 | drop(buf); 1377 | assert_eq!(0, split.capacity()); 1378 | assert_eq!(true, split.try_reclaim(6)); 1379 | assert_eq!(false, split.try_reclaim(cap + 1)); 1380 | } 1381 | 1382 | #[test] 1383 | fn try_reclaim_vec() { 1384 | let mut buf = BytesMut::with_capacity(6); 1385 | buf.put_slice(b"abc"); 1386 | // Reclaiming a ludicrous amount of space should calmly return false 1387 | assert_eq!(false, buf.try_reclaim(usize::MAX)); 1388 | 1389 | assert_eq!(false, buf.try_reclaim(6)); 1390 | buf.advance(2); 1391 | assert_eq!(4, buf.capacity()); 1392 | // We can reclaim 5 bytes, because the byte in the buffer can be moved to the front. 6 bytes 1393 | // cannot be reclaimed because there is already one byte stored 1394 | assert_eq!(false, buf.try_reclaim(6)); 1395 | assert_eq!(true, buf.try_reclaim(5)); 1396 | buf.advance(1); 1397 | assert_eq!(true, buf.try_reclaim(6)); 1398 | assert_eq!(6, buf.capacity()); 1399 | } 1400 | 1401 | #[test] 1402 | fn try_reclaim_arc() { 1403 | let mut buf = BytesMut::with_capacity(6); 1404 | buf.put_slice(b"abc"); 1405 | let x = buf.split().freeze(); 1406 | buf.put_slice(b"def"); 1407 | // Reclaiming a ludicrous amount of space should calmly return false 1408 | assert_eq!(false, buf.try_reclaim(usize::MAX)); 1409 | 1410 | let y = buf.split().freeze(); 1411 | let z = y.clone(); 1412 | assert_eq!(false, buf.try_reclaim(6)); 1413 | drop(x); 1414 | drop(z); 1415 | assert_eq!(false, buf.try_reclaim(6)); 1416 | drop(y); 1417 | assert_eq!(true, buf.try_reclaim(6)); 1418 | assert_eq!(6, buf.capacity()); 1419 | assert_eq!(0, buf.len()); 1420 | buf.put_slice(b"abc"); 1421 | buf.put_slice(b"def"); 1422 | assert_eq!(6, buf.capacity()); 1423 | assert_eq!(6, buf.len()); 1424 | assert_eq!(false, buf.try_reclaim(6)); 1425 | buf.advance(4); 1426 | assert_eq!(true, buf.try_reclaim(4)); 1427 | buf.advance(2); 1428 | assert_eq!(true, buf.try_reclaim(6)); 1429 | } 1430 | 1431 | #[test] 1432 | fn slice_empty_addr() { 1433 | let buf = Bytes::from(vec![0; 1024]); 1434 | 1435 | let ptr_start = buf.as_ptr(); 1436 | let ptr_end = ptr_start.wrapping_add(1024); 1437 | 1438 | let empty_end = buf.slice(1024..); 1439 | assert_eq!(empty_end.len(), 0); 1440 | assert_eq!(empty_end.as_ptr(), ptr_end); 1441 | 1442 | let empty_start = buf.slice(..0); 1443 | assert_eq!(empty_start.len(), 0); 1444 | assert_eq!(empty_start.as_ptr(), ptr_start); 1445 | 1446 | // Is miri happy about the provenance? 1447 | let _ = &empty_end[..]; 1448 | let _ = &empty_start[..]; 1449 | } 1450 | 1451 | #[test] 1452 | fn split_off_empty_addr() { 1453 | let mut buf = Bytes::from(vec![0; 1024]); 1454 | 1455 | let ptr_start = buf.as_ptr(); 1456 | let ptr_end = ptr_start.wrapping_add(1024); 1457 | 1458 | let empty_end = buf.split_off(1024); 1459 | assert_eq!(empty_end.len(), 0); 1460 | assert_eq!(empty_end.as_ptr(), ptr_end); 1461 | 1462 | let _ = buf.split_off(0); 1463 | assert_eq!(buf.len(), 0); 1464 | assert_eq!(buf.as_ptr(), ptr_start); 1465 | 1466 | // Is miri happy about the provenance? 1467 | let _ = &empty_end[..]; 1468 | let _ = &buf[..]; 1469 | } 1470 | 1471 | #[test] 1472 | fn split_to_empty_addr() { 1473 | let mut buf = Bytes::from(vec![0; 1024]); 1474 | 1475 | let ptr_start = buf.as_ptr(); 1476 | let ptr_end = ptr_start.wrapping_add(1024); 1477 | 1478 | let empty_start = buf.split_to(0); 1479 | assert_eq!(empty_start.len(), 0); 1480 | assert_eq!(empty_start.as_ptr(), ptr_start); 1481 | 1482 | let _ = buf.split_to(1024); 1483 | assert_eq!(buf.len(), 0); 1484 | assert_eq!(buf.as_ptr(), ptr_end); 1485 | 1486 | // Is miri happy about the provenance? 1487 | let _ = &empty_start[..]; 1488 | let _ = &buf[..]; 1489 | } 1490 | 1491 | #[test] 1492 | fn split_off_empty_addr_mut() { 1493 | let mut buf = BytesMut::from([0; 1024].as_slice()); 1494 | 1495 | let ptr_start = buf.as_ptr(); 1496 | let ptr_end = ptr_start.wrapping_add(1024); 1497 | 1498 | let empty_end = buf.split_off(1024); 1499 | assert_eq!(empty_end.len(), 0); 1500 | assert_eq!(empty_end.as_ptr(), ptr_end); 1501 | 1502 | let _ = buf.split_off(0); 1503 | assert_eq!(buf.len(), 0); 1504 | assert_eq!(buf.as_ptr(), ptr_start); 1505 | 1506 | // Is miri happy about the provenance? 1507 | let _ = &empty_end[..]; 1508 | let _ = &buf[..]; 1509 | } 1510 | 1511 | #[test] 1512 | fn split_to_empty_addr_mut() { 1513 | let mut buf = BytesMut::from([0; 1024].as_slice()); 1514 | 1515 | let ptr_start = buf.as_ptr(); 1516 | let ptr_end = ptr_start.wrapping_add(1024); 1517 | 1518 | let empty_start = buf.split_to(0); 1519 | assert_eq!(empty_start.len(), 0); 1520 | assert_eq!(empty_start.as_ptr(), ptr_start); 1521 | 1522 | let _ = buf.split_to(1024); 1523 | assert_eq!(buf.len(), 0); 1524 | assert_eq!(buf.as_ptr(), ptr_end); 1525 | 1526 | // Is miri happy about the provenance? 1527 | let _ = &empty_start[..]; 1528 | let _ = &buf[..]; 1529 | } 1530 | 1531 | #[derive(Clone)] 1532 | struct SharedAtomicCounter(Arc); 1533 | 1534 | impl SharedAtomicCounter { 1535 | pub fn new() -> Self { 1536 | SharedAtomicCounter(Arc::new(AtomicUsize::new(0))) 1537 | } 1538 | 1539 | pub fn increment(&self) { 1540 | self.0.fetch_add(1, Ordering::AcqRel); 1541 | } 1542 | 1543 | pub fn get(&self) -> usize { 1544 | self.0.load(Ordering::Acquire) 1545 | } 1546 | } 1547 | 1548 | #[derive(Clone)] 1549 | struct OwnedTester { 1550 | buf: [u8; L], 1551 | drop_count: SharedAtomicCounter, 1552 | pub panic_as_ref: bool, 1553 | } 1554 | 1555 | impl OwnedTester { 1556 | fn new(buf: [u8; L], drop_count: SharedAtomicCounter) -> Self { 1557 | Self { 1558 | buf, 1559 | drop_count, 1560 | panic_as_ref: false, 1561 | } 1562 | } 1563 | } 1564 | 1565 | impl AsRef<[u8]> for OwnedTester { 1566 | fn as_ref(&self) -> &[u8] { 1567 | if self.panic_as_ref { 1568 | panic!("test-triggered panic in `AsRef<[u8]> for OwnedTester`"); 1569 | } 1570 | self.buf.as_slice() 1571 | } 1572 | } 1573 | 1574 | impl Drop for OwnedTester { 1575 | fn drop(&mut self) { 1576 | self.drop_count.increment(); 1577 | } 1578 | } 1579 | 1580 | #[test] 1581 | fn owned_is_unique_always_false() { 1582 | let b1 = Bytes::from_owner([1, 2, 3, 4, 5, 6, 7]); 1583 | assert!(!b1.is_unique()); // even if ref_cnt == 1 1584 | let b2 = b1.clone(); 1585 | assert!(!b1.is_unique()); 1586 | assert!(!b2.is_unique()); 1587 | drop(b1); 1588 | assert!(!b2.is_unique()); // even if ref_cnt == 1 1589 | } 1590 | 1591 | #[test] 1592 | fn owned_buf_sharing() { 1593 | let buf = [1, 2, 3, 4, 5, 6, 7]; 1594 | let b1 = Bytes::from_owner(buf); 1595 | let b2 = b1.clone(); 1596 | assert_eq!(&buf[..], &b1[..]); 1597 | assert_eq!(&buf[..], &b2[..]); 1598 | assert_eq!(b1.as_ptr(), b2.as_ptr()); 1599 | assert_eq!(b1.len(), b2.len()); 1600 | assert_eq!(b1.len(), buf.len()); 1601 | } 1602 | 1603 | #[test] 1604 | fn owned_buf_slicing() { 1605 | let b1 = Bytes::from_owner(SHORT); 1606 | assert_eq!(SHORT, &b1[..]); 1607 | let b2 = b1.slice(1..(b1.len() - 1)); 1608 | assert_eq!(&SHORT[1..(SHORT.len() - 1)], b2); 1609 | assert_eq!(unsafe { SHORT.as_ptr().add(1) }, b2.as_ptr()); 1610 | assert_eq!(SHORT.len() - 2, b2.len()); 1611 | } 1612 | 1613 | #[test] 1614 | fn owned_dropped_exactly_once() { 1615 | let buf: [u8; 5] = [1, 2, 3, 4, 5]; 1616 | let drop_counter = SharedAtomicCounter::new(); 1617 | let owner = OwnedTester::new(buf, drop_counter.clone()); 1618 | let b1 = Bytes::from_owner(owner); 1619 | let b2 = b1.clone(); 1620 | assert_eq!(drop_counter.get(), 0); 1621 | drop(b1); 1622 | assert_eq!(drop_counter.get(), 0); 1623 | let b3 = b2.slice(1..b2.len() - 1); 1624 | drop(b2); 1625 | assert_eq!(drop_counter.get(), 0); 1626 | drop(b3); 1627 | assert_eq!(drop_counter.get(), 1); 1628 | } 1629 | 1630 | #[test] 1631 | fn owned_to_mut() { 1632 | let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 1633 | let drop_counter = SharedAtomicCounter::new(); 1634 | let owner = OwnedTester::new(buf, drop_counter.clone()); 1635 | let b1 = Bytes::from_owner(owner); 1636 | 1637 | // Holding an owner will fail converting to a BytesMut, 1638 | // even when the bytes instance has a ref_cnt == 1. 1639 | let b1 = b1.try_into_mut().unwrap_err(); 1640 | 1641 | // That said, it's still possible, just not cheap. 1642 | let bm1: BytesMut = b1.into(); 1643 | let new_buf = &bm1[..]; 1644 | assert_eq!(new_buf, &buf[..]); 1645 | 1646 | // `.into::()` has correctly dropped the owner 1647 | assert_eq!(drop_counter.get(), 1); 1648 | } 1649 | 1650 | #[test] 1651 | fn owned_to_vec() { 1652 | let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 1653 | let drop_counter = SharedAtomicCounter::new(); 1654 | let owner = OwnedTester::new(buf, drop_counter.clone()); 1655 | let b1 = Bytes::from_owner(owner); 1656 | 1657 | let v1 = b1.to_vec(); 1658 | assert_eq!(&v1[..], &buf[..]); 1659 | assert_eq!(&v1[..], &b1[..]); 1660 | 1661 | drop(b1); 1662 | assert_eq!(drop_counter.get(), 1); 1663 | } 1664 | 1665 | #[test] 1666 | fn owned_into_vec() { 1667 | let drop_counter = SharedAtomicCounter::new(); 1668 | let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 1669 | let owner = OwnedTester::new(buf, drop_counter.clone()); 1670 | let b1 = Bytes::from_owner(owner); 1671 | 1672 | let v1: Vec = b1.into(); 1673 | assert_eq!(&v1[..], &buf[..]); 1674 | // into() vec will copy out of the owner and drop it 1675 | assert_eq!(drop_counter.get(), 1); 1676 | } 1677 | 1678 | #[test] 1679 | #[cfg_attr(not(panic = "unwind"), ignore)] 1680 | fn owned_safe_drop_on_as_ref_panic() { 1681 | let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 1682 | let drop_counter = SharedAtomicCounter::new(); 1683 | let mut owner = OwnedTester::new(buf, drop_counter.clone()); 1684 | owner.panic_as_ref = true; 1685 | 1686 | let result = panic::catch_unwind(AssertUnwindSafe(|| { 1687 | let _ = Bytes::from_owner(owner); 1688 | })); 1689 | 1690 | assert!(result.is_err()); 1691 | assert_eq!(drop_counter.get(), 1); 1692 | } 1693 | -------------------------------------------------------------------------------- /tests/test_bytes_odd_alloc.rs: -------------------------------------------------------------------------------- 1 | //! Test using `Bytes` with an allocator that hands out "odd" pointers for 2 | //! vectors (pointers where the LSB is set). 3 | 4 | #![cfg(not(miri))] // Miri does not support custom allocators (also, Miri is "odd" by default with 50% chance) 5 | 6 | use std::alloc::{GlobalAlloc, Layout, System}; 7 | use std::ptr; 8 | 9 | use bytes::{Bytes, BytesMut}; 10 | 11 | #[global_allocator] 12 | static ODD: Odd = Odd; 13 | 14 | struct Odd; 15 | 16 | unsafe impl GlobalAlloc for Odd { 17 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 18 | if layout.align() == 1 && layout.size() > 0 { 19 | // Allocate slightly bigger so that we can offset the pointer by 1 20 | let size = layout.size() + 1; 21 | let new_layout = match Layout::from_size_align(size, 1) { 22 | Ok(layout) => layout, 23 | Err(_err) => return ptr::null_mut(), 24 | }; 25 | let ptr = System.alloc(new_layout); 26 | if !ptr.is_null() { 27 | ptr.offset(1) 28 | } else { 29 | ptr 30 | } 31 | } else { 32 | System.alloc(layout) 33 | } 34 | } 35 | 36 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 37 | if layout.align() == 1 && layout.size() > 0 { 38 | let size = layout.size() + 1; 39 | let new_layout = match Layout::from_size_align(size, 1) { 40 | Ok(layout) => layout, 41 | Err(_err) => std::process::abort(), 42 | }; 43 | System.dealloc(ptr.offset(-1), new_layout); 44 | } else { 45 | System.dealloc(ptr, layout); 46 | } 47 | } 48 | } 49 | 50 | #[test] 51 | fn sanity_check_odd_allocator() { 52 | let vec = vec![33u8; 1024]; 53 | let p = vec.as_ptr() as usize; 54 | assert!(p & 0x1 == 0x1, "{:#b}", p); 55 | } 56 | 57 | #[test] 58 | fn test_bytes_from_vec_drop() { 59 | let vec = vec![33u8; 1024]; 60 | let _b = Bytes::from(vec); 61 | } 62 | 63 | #[test] 64 | fn test_bytes_clone_drop() { 65 | let vec = vec![33u8; 1024]; 66 | let b1 = Bytes::from(vec); 67 | let _b2 = b1.clone(); 68 | } 69 | 70 | #[test] 71 | fn test_bytes_into_vec() { 72 | let vec = vec![33u8; 1024]; 73 | 74 | // Test cases where kind == KIND_VEC 75 | let b1 = Bytes::from(vec.clone()); 76 | assert_eq!(Vec::from(b1), vec); 77 | 78 | // Test cases where kind == KIND_ARC, ref_cnt == 1 79 | let b1 = Bytes::from(vec.clone()); 80 | drop(b1.clone()); 81 | assert_eq!(Vec::from(b1), vec); 82 | 83 | // Test cases where kind == KIND_ARC, ref_cnt == 2 84 | let b1 = Bytes::from(vec.clone()); 85 | let b2 = b1.clone(); 86 | assert_eq!(Vec::from(b1), vec); 87 | 88 | // Test cases where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 89 | assert_eq!(Vec::from(b2), vec); 90 | 91 | // Test cases where offset != 0 92 | let mut b1 = Bytes::from(vec.clone()); 93 | let b2 = b1.split_off(20); 94 | 95 | assert_eq!(Vec::from(b2), vec[20..]); 96 | assert_eq!(Vec::from(b1), vec[..20]); 97 | } 98 | 99 | #[test] 100 | fn test_bytesmut_from_bytes_vec() { 101 | let vec = vec![33u8; 1024]; 102 | 103 | // Test case where kind == KIND_VEC 104 | let b1 = Bytes::from(vec.clone()); 105 | let b1m = BytesMut::from(b1); 106 | assert_eq!(b1m, vec); 107 | } 108 | 109 | #[test] 110 | fn test_bytesmut_from_bytes_arc_1() { 111 | let vec = vec![33u8; 1024]; 112 | 113 | // Test case where kind == KIND_ARC, ref_cnt == 1 114 | let b1 = Bytes::from(vec.clone()); 115 | drop(b1.clone()); 116 | let b1m = BytesMut::from(b1); 117 | assert_eq!(b1m, vec); 118 | } 119 | 120 | #[test] 121 | fn test_bytesmut_from_bytes_arc_2() { 122 | let vec = vec![33u8; 1024]; 123 | 124 | // Test case where kind == KIND_ARC, ref_cnt == 2 125 | let b1 = Bytes::from(vec.clone()); 126 | let b2 = b1.clone(); 127 | let b1m = BytesMut::from(b1); 128 | assert_eq!(b1m, vec); 129 | 130 | // Test case where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 131 | let b2m = BytesMut::from(b2); 132 | assert_eq!(b2m, vec); 133 | } 134 | 135 | #[test] 136 | fn test_bytesmut_from_bytes_arc_offset() { 137 | let vec = vec![33u8; 1024]; 138 | 139 | // Test case where offset != 0 140 | let mut b1 = Bytes::from(vec.clone()); 141 | let b2 = b1.split_off(20); 142 | let b1m = BytesMut::from(b1); 143 | let b2m = BytesMut::from(b2); 144 | 145 | assert_eq!(b2m, vec[20..]); 146 | assert_eq!(b1m, vec[..20]); 147 | } 148 | -------------------------------------------------------------------------------- /tests/test_bytes_vec_alloc.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(miri))] 2 | use std::alloc::{GlobalAlloc, Layout, System}; 3 | use std::ptr::null_mut; 4 | use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; 5 | 6 | use bytes::{Buf, Bytes}; 7 | 8 | #[global_allocator] 9 | static LEDGER: Ledger = Ledger::new(); 10 | 11 | const LEDGER_LENGTH: usize = 1024 * 1024; 12 | 13 | struct Ledger { 14 | alloc_table: [(AtomicPtr, AtomicUsize); LEDGER_LENGTH], 15 | } 16 | 17 | impl Ledger { 18 | const fn new() -> Self { 19 | const ELEM: (AtomicPtr, AtomicUsize) = 20 | (AtomicPtr::new(null_mut()), AtomicUsize::new(0)); 21 | let alloc_table = [ELEM; LEDGER_LENGTH]; 22 | 23 | Self { alloc_table } 24 | } 25 | 26 | /// Iterate over our table until we find an open entry, then insert into said entry 27 | fn insert(&self, ptr: *mut u8, size: usize) { 28 | for (entry_ptr, entry_size) in self.alloc_table.iter() { 29 | // SeqCst is good enough here, we don't care about perf, i just want to be correct! 30 | if entry_ptr 31 | .compare_exchange(null_mut(), ptr, Ordering::SeqCst, Ordering::SeqCst) 32 | .is_ok() 33 | { 34 | entry_size.store(size, Ordering::SeqCst); 35 | return; 36 | } 37 | } 38 | 39 | panic!("Ledger ran out of space."); 40 | } 41 | 42 | fn remove(&self, ptr: *mut u8) -> usize { 43 | for (entry_ptr, entry_size) in self.alloc_table.iter() { 44 | // set the value to be something that will never try and be deallocated, so that we 45 | // don't have any chance of a race condition 46 | // 47 | // dont worry, LEDGER_LENGTH is really long to compensate for us not reclaiming space 48 | if entry_ptr 49 | .compare_exchange( 50 | ptr, 51 | invalid_ptr(usize::MAX), 52 | Ordering::SeqCst, 53 | Ordering::SeqCst, 54 | ) 55 | .is_ok() 56 | { 57 | return entry_size.load(Ordering::SeqCst); 58 | } 59 | } 60 | 61 | panic!("Couldn't find a matching entry for {:x?}", ptr); 62 | } 63 | } 64 | 65 | unsafe impl GlobalAlloc for Ledger { 66 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 67 | let size = layout.size(); 68 | let ptr = System.alloc(layout); 69 | self.insert(ptr, size); 70 | ptr 71 | } 72 | 73 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 74 | let orig_size = self.remove(ptr); 75 | 76 | if orig_size != layout.size() { 77 | panic!( 78 | "bad dealloc: alloc size was {}, dealloc size is {}", 79 | orig_size, 80 | layout.size() 81 | ); 82 | } else { 83 | System.dealloc(ptr, layout); 84 | } 85 | } 86 | } 87 | 88 | #[test] 89 | fn test_bytes_advance() { 90 | let mut bytes = Bytes::from(vec![10, 20, 30]); 91 | bytes.advance(1); 92 | drop(bytes); 93 | } 94 | 95 | #[test] 96 | fn test_bytes_truncate() { 97 | let mut bytes = Bytes::from(vec![10, 20, 30]); 98 | bytes.truncate(2); 99 | drop(bytes); 100 | } 101 | 102 | #[test] 103 | fn test_bytes_truncate_and_advance() { 104 | let mut bytes = Bytes::from(vec![10, 20, 30]); 105 | bytes.truncate(2); 106 | bytes.advance(1); 107 | drop(bytes); 108 | } 109 | 110 | /// Returns a dangling pointer with the given address. This is used to store 111 | /// integer data in pointer fields. 112 | #[inline] 113 | fn invalid_ptr(addr: usize) -> *mut T { 114 | let ptr = std::ptr::null_mut::().wrapping_add(addr); 115 | debug_assert_eq!(ptr as usize, addr); 116 | ptr.cast::() 117 | } 118 | 119 | #[test] 120 | fn test_bytes_into_vec() { 121 | let vec = vec![33u8; 1024]; 122 | 123 | // Test cases where kind == KIND_VEC 124 | let b1 = Bytes::from(vec.clone()); 125 | assert_eq!(Vec::from(b1), vec); 126 | 127 | // Test cases where kind == KIND_ARC, ref_cnt == 1 128 | let b1 = Bytes::from(vec.clone()); 129 | drop(b1.clone()); 130 | assert_eq!(Vec::from(b1), vec); 131 | 132 | // Test cases where kind == KIND_ARC, ref_cnt == 2 133 | let b1 = Bytes::from(vec.clone()); 134 | let b2 = b1.clone(); 135 | assert_eq!(Vec::from(b1), vec); 136 | 137 | // Test cases where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 138 | assert_eq!(Vec::from(b2), vec); 139 | 140 | // Test cases where offset != 0 141 | let mut b1 = Bytes::from(vec.clone()); 142 | let b2 = b1.split_off(20); 143 | 144 | assert_eq!(Vec::from(b2), vec[20..]); 145 | assert_eq!(Vec::from(b1), vec[..20]); 146 | } 147 | -------------------------------------------------------------------------------- /tests/test_chain.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::{Buf, BufMut, Bytes}; 4 | #[cfg(feature = "std")] 5 | use std::io::IoSlice; 6 | 7 | #[test] 8 | fn collect_two_bufs() { 9 | let a = Bytes::from(&b"hello"[..]); 10 | let b = Bytes::from(&b"world"[..]); 11 | 12 | let res = a.chain(b).copy_to_bytes(10); 13 | assert_eq!(res, &b"helloworld"[..]); 14 | } 15 | 16 | #[test] 17 | fn writing_chained() { 18 | let mut a = [0u8; 64]; 19 | let mut b = [0u8; 64]; 20 | 21 | { 22 | let mut buf = (&mut a[..]).chain_mut(&mut b[..]); 23 | 24 | for i in 0u8..128 { 25 | buf.put_u8(i); 26 | } 27 | } 28 | 29 | for i in 0..64 { 30 | let expect = i as u8; 31 | assert_eq!(expect, a[i]); 32 | assert_eq!(expect + 64, b[i]); 33 | } 34 | } 35 | 36 | #[test] 37 | fn iterating_two_bufs() { 38 | let a = Bytes::from(&b"hello"[..]); 39 | let b = Bytes::from(&b"world"[..]); 40 | 41 | let res: Vec = a.chain(b).into_iter().collect(); 42 | assert_eq!(res, &b"helloworld"[..]); 43 | } 44 | 45 | #[cfg(feature = "std")] 46 | #[test] 47 | fn vectored_read() { 48 | let a = Bytes::from(&b"hello"[..]); 49 | let b = Bytes::from(&b"world"[..]); 50 | 51 | let mut buf = a.chain(b); 52 | 53 | { 54 | let b1: &[u8] = &mut []; 55 | let b2: &[u8] = &mut []; 56 | let b3: &[u8] = &mut []; 57 | let b4: &[u8] = &mut []; 58 | let mut iovecs = [ 59 | IoSlice::new(b1), 60 | IoSlice::new(b2), 61 | IoSlice::new(b3), 62 | IoSlice::new(b4), 63 | ]; 64 | 65 | assert_eq!(2, buf.chunks_vectored(&mut iovecs)); 66 | assert_eq!(iovecs[0][..], b"hello"[..]); 67 | assert_eq!(iovecs[1][..], b"world"[..]); 68 | assert_eq!(iovecs[2][..], b""[..]); 69 | assert_eq!(iovecs[3][..], b""[..]); 70 | } 71 | 72 | buf.advance(2); 73 | 74 | { 75 | let b1: &[u8] = &mut []; 76 | let b2: &[u8] = &mut []; 77 | let b3: &[u8] = &mut []; 78 | let b4: &[u8] = &mut []; 79 | let mut iovecs = [ 80 | IoSlice::new(b1), 81 | IoSlice::new(b2), 82 | IoSlice::new(b3), 83 | IoSlice::new(b4), 84 | ]; 85 | 86 | assert_eq!(2, buf.chunks_vectored(&mut iovecs)); 87 | assert_eq!(iovecs[0][..], b"llo"[..]); 88 | assert_eq!(iovecs[1][..], b"world"[..]); 89 | assert_eq!(iovecs[2][..], b""[..]); 90 | assert_eq!(iovecs[3][..], b""[..]); 91 | } 92 | 93 | buf.advance(3); 94 | 95 | { 96 | let b1: &[u8] = &mut []; 97 | let b2: &[u8] = &mut []; 98 | let b3: &[u8] = &mut []; 99 | let b4: &[u8] = &mut []; 100 | let mut iovecs = [ 101 | IoSlice::new(b1), 102 | IoSlice::new(b2), 103 | IoSlice::new(b3), 104 | IoSlice::new(b4), 105 | ]; 106 | 107 | assert_eq!(1, buf.chunks_vectored(&mut iovecs)); 108 | assert_eq!(iovecs[0][..], b"world"[..]); 109 | assert_eq!(iovecs[1][..], b""[..]); 110 | assert_eq!(iovecs[2][..], b""[..]); 111 | assert_eq!(iovecs[3][..], b""[..]); 112 | } 113 | 114 | buf.advance(3); 115 | 116 | { 117 | let b1: &[u8] = &mut []; 118 | let b2: &[u8] = &mut []; 119 | let b3: &[u8] = &mut []; 120 | let b4: &[u8] = &mut []; 121 | let mut iovecs = [ 122 | IoSlice::new(b1), 123 | IoSlice::new(b2), 124 | IoSlice::new(b3), 125 | IoSlice::new(b4), 126 | ]; 127 | 128 | assert_eq!(1, buf.chunks_vectored(&mut iovecs)); 129 | assert_eq!(iovecs[0][..], b"ld"[..]); 130 | assert_eq!(iovecs[1][..], b""[..]); 131 | assert_eq!(iovecs[2][..], b""[..]); 132 | assert_eq!(iovecs[3][..], b""[..]); 133 | } 134 | } 135 | 136 | #[test] 137 | fn chain_growing_buffer() { 138 | let mut buff = [' ' as u8; 10]; 139 | let mut vec = b"wassup".to_vec(); 140 | 141 | let mut chained = (&mut buff[..]).chain_mut(&mut vec).chain_mut(Vec::new()); // Required for potential overflow because remaining_mut for Vec is isize::MAX - vec.len(), but for chain_mut is usize::MAX 142 | 143 | chained.put_slice(b"hey there123123"); 144 | 145 | assert_eq!(&buff, b"hey there1"); 146 | assert_eq!(&vec, b"wassup23123"); 147 | } 148 | 149 | #[test] 150 | fn chain_overflow_remaining_mut() { 151 | let mut chained = Vec::::new().chain_mut(Vec::new()).chain_mut(Vec::new()); 152 | 153 | assert_eq!(chained.remaining_mut(), usize::MAX); 154 | chained.put_slice(&[0; 256]); 155 | assert_eq!(chained.remaining_mut(), usize::MAX); 156 | } 157 | 158 | #[test] 159 | fn chain_get_bytes() { 160 | let mut ab = Bytes::copy_from_slice(b"ab"); 161 | let mut cd = Bytes::copy_from_slice(b"cd"); 162 | let ab_ptr = ab.as_ptr(); 163 | let cd_ptr = cd.as_ptr(); 164 | let mut chain = (&mut ab).chain(&mut cd); 165 | let a = chain.copy_to_bytes(1); 166 | let bc = chain.copy_to_bytes(2); 167 | let d = chain.copy_to_bytes(1); 168 | 169 | assert_eq!(Bytes::copy_from_slice(b"a"), a); 170 | assert_eq!(Bytes::copy_from_slice(b"bc"), bc); 171 | assert_eq!(Bytes::copy_from_slice(b"d"), d); 172 | 173 | // assert `get_bytes` did not allocate 174 | assert_eq!(ab_ptr, a.as_ptr()); 175 | // assert `get_bytes` did not allocate 176 | assert_eq!(cd_ptr.wrapping_offset(1), d.as_ptr()); 177 | } 178 | -------------------------------------------------------------------------------- /tests/test_debug.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::Bytes; 4 | 5 | #[test] 6 | fn fmt() { 7 | let vec: Vec<_> = (0..0x100).map(|b| b as u8).collect(); 8 | 9 | let expected = "b\"\ 10 | \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\ 11 | \\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\ 12 | \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\ 13 | \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\ 14 | \x20!\\\"#$%&'()*+,-./0123456789:;<=>?\ 15 | @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\ 16 | `abcdefghijklmnopqrstuvwxyz{|}~\\x7f\ 17 | \\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\ 18 | \\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\ 19 | \\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\ 20 | \\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\ 21 | \\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\ 22 | \\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\ 23 | \\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\ 24 | \\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\ 25 | \\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\ 26 | \\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\ 27 | \\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\ 28 | \\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\ 29 | \\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\ 30 | \\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\ 31 | \\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\ 32 | \\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\""; 33 | 34 | assert_eq!(expected, format!("{:?}", Bytes::from(vec))); 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_iter.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::{buf::IntoIter, Bytes}; 4 | 5 | #[test] 6 | fn iter_len() { 7 | let buf = Bytes::from_static(b"hello world"); 8 | let iter = IntoIter::new(buf); 9 | 10 | assert_eq!(iter.size_hint(), (11, Some(11))); 11 | assert_eq!(iter.len(), 11); 12 | } 13 | 14 | #[test] 15 | fn empty_iter_len() { 16 | let buf = Bytes::new(); 17 | let iter = IntoIter::new(buf); 18 | 19 | assert_eq!(iter.size_hint(), (0, Some(0))); 20 | assert_eq!(iter.len(), 0); 21 | } 22 | -------------------------------------------------------------------------------- /tests/test_limit.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::{buf::Limit, BufMut}; 4 | 5 | #[test] 6 | fn long_limit() { 7 | let buf = &mut [0u8; 10]; 8 | let limit = buf.limit(100); 9 | assert_eq!(10, limit.remaining_mut()); 10 | assert_eq!(&[0u8; 10], &limit.get_ref()[..]); 11 | } 12 | 13 | #[test] 14 | fn limit_get_mut() { 15 | let buf = &mut [0u8; 128]; 16 | let mut limit = buf.limit(10); 17 | assert_eq!(10, limit.remaining_mut()); 18 | assert_eq!(&mut [0u8; 128], &limit.get_mut()[..]); 19 | } 20 | 21 | #[test] 22 | fn limit_set_limit() { 23 | let buf = &mut [0u8; 128]; 24 | let mut limit = buf.limit(10); 25 | assert_eq!(10, Limit::limit(&limit)); 26 | limit.set_limit(5); 27 | assert_eq!(5, Limit::limit(&limit)); 28 | } 29 | 30 | #[test] 31 | fn limit_chunk_mut() { 32 | let buf = &mut [0u8; 20]; 33 | let mut limit = buf.limit(10); 34 | assert_eq!(10, limit.chunk_mut().len()); 35 | 36 | let buf = &mut [0u8; 10]; 37 | let mut limit = buf.limit(20); 38 | assert_eq!(10, limit.chunk_mut().len()); 39 | } 40 | 41 | #[test] 42 | #[should_panic = "advance out of bounds"] 43 | fn limit_advance_mut_panic_1() { 44 | let buf = &mut [0u8; 10]; 45 | let mut limit = buf.limit(100); 46 | unsafe { 47 | limit.advance_mut(50); 48 | } 49 | } 50 | 51 | #[test] 52 | #[should_panic = "cnt <= self.limit"] 53 | fn limit_advance_mut_panic_2() { 54 | let buf = &mut [0u8; 100]; 55 | let mut limit = buf.limit(10); 56 | unsafe { 57 | limit.advance_mut(50); 58 | } 59 | } 60 | 61 | #[test] 62 | fn limit_advance_mut() { 63 | let buf = &mut [0u8; 100]; 64 | let mut limit = buf.limit(10); 65 | unsafe { 66 | limit.advance_mut(5); 67 | } 68 | assert_eq!(5, limit.remaining_mut()); 69 | assert_eq!(5, limit.chunk_mut().len()); 70 | } 71 | 72 | #[test] 73 | fn limit_into_inner() { 74 | let buf_arr = *b"hello world"; 75 | let buf: &mut [u8] = &mut buf_arr.clone(); 76 | let mut limit = buf.limit(4); 77 | let mut dst = vec![]; 78 | 79 | unsafe { 80 | limit.advance_mut(2); 81 | } 82 | 83 | let buf = limit.into_inner(); 84 | dst.put(&buf[..]); 85 | assert_eq!(*dst, b"llo world"[..]); 86 | } 87 | -------------------------------------------------------------------------------- /tests/test_reader.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![cfg(feature = "std")] 3 | 4 | use std::io::{BufRead, Read}; 5 | 6 | use bytes::Buf; 7 | 8 | #[test] 9 | fn read() { 10 | let buf1 = &b"hello "[..]; 11 | let buf2 = &b"world"[..]; 12 | let buf = Buf::chain(buf1, buf2); // Disambiguate with Read::chain 13 | let mut buffer = Vec::new(); 14 | buf.reader().read_to_end(&mut buffer).unwrap(); 15 | assert_eq!(b"hello world", &buffer[..]); 16 | } 17 | 18 | #[test] 19 | fn buf_read() { 20 | let buf1 = &b"hell"[..]; 21 | let buf2 = &b"o\nworld"[..]; 22 | let mut reader = Buf::chain(buf1, buf2).reader(); 23 | let mut line = String::new(); 24 | reader.read_line(&mut line).unwrap(); 25 | assert_eq!("hello\n", &line); 26 | line.clear(); 27 | reader.read_line(&mut line).unwrap(); 28 | assert_eq!("world", &line); 29 | } 30 | 31 | #[test] 32 | fn get_mut() { 33 | let buf = &b"hello world"[..]; 34 | let mut reader = buf.reader(); 35 | let buf_mut = reader.get_mut(); 36 | assert_eq!(11, buf_mut.remaining()); 37 | assert_eq!(b"hello world", buf_mut); 38 | } 39 | -------------------------------------------------------------------------------- /tests/test_serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde")] 2 | #![warn(rust_2018_idioms)] 3 | 4 | use serde_test::{assert_tokens, Token}; 5 | 6 | #[test] 7 | fn test_ser_de_empty() { 8 | let b = bytes::Bytes::new(); 9 | assert_tokens(&b, &[Token::Bytes(b"")]); 10 | let b = bytes::BytesMut::with_capacity(0); 11 | assert_tokens(&b, &[Token::Bytes(b"")]); 12 | } 13 | 14 | #[test] 15 | fn test_ser_de() { 16 | let b = bytes::Bytes::from(&b"bytes"[..]); 17 | assert_tokens(&b, &[Token::Bytes(b"bytes")]); 18 | let b = bytes::BytesMut::from(&b"bytes"[..]); 19 | assert_tokens(&b, &[Token::Bytes(b"bytes")]); 20 | } 21 | -------------------------------------------------------------------------------- /tests/test_take.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | 3 | use bytes::buf::Buf; 4 | use bytes::Bytes; 5 | 6 | #[test] 7 | fn long_take() { 8 | // Tests that get a take with a size greater than the buffer length will not 9 | // overrun the buffer. Regression test for #138. 10 | let buf = b"hello world".take(100); 11 | assert_eq!(11, buf.remaining()); 12 | assert_eq!(b"hello world", buf.chunk()); 13 | } 14 | 15 | #[test] 16 | fn take_copy_to_bytes() { 17 | let mut abcd = Bytes::copy_from_slice(b"abcd"); 18 | let abcd_ptr = abcd.as_ptr(); 19 | let mut take = (&mut abcd).take(2); 20 | let a = take.copy_to_bytes(1); 21 | assert_eq!(Bytes::copy_from_slice(b"a"), a); 22 | // assert `to_bytes` did not allocate 23 | assert_eq!(abcd_ptr, a.as_ptr()); 24 | assert_eq!(Bytes::copy_from_slice(b"bcd"), abcd); 25 | } 26 | 27 | #[test] 28 | #[should_panic] 29 | fn take_copy_to_bytes_panics() { 30 | let abcd = Bytes::copy_from_slice(b"abcd"); 31 | abcd.take(2).copy_to_bytes(3); 32 | } 33 | 34 | #[cfg(feature = "std")] 35 | #[test] 36 | fn take_chunks_vectored() { 37 | fn chain() -> impl Buf { 38 | Bytes::from([1, 2, 3].to_vec()).chain(Bytes::from([4, 5, 6].to_vec())) 39 | } 40 | 41 | { 42 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 43 | let take = chain().take(0); 44 | assert_eq!(take.chunks_vectored(&mut dst), 0); 45 | } 46 | 47 | { 48 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 49 | let take = chain().take(1); 50 | assert_eq!(take.chunks_vectored(&mut dst), 1); 51 | assert_eq!(&*dst[0], &[1]); 52 | } 53 | 54 | { 55 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 56 | let take = chain().take(3); 57 | assert_eq!(take.chunks_vectored(&mut dst), 1); 58 | assert_eq!(&*dst[0], &[1, 2, 3]); 59 | } 60 | 61 | { 62 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 63 | let take = chain().take(4); 64 | assert_eq!(take.chunks_vectored(&mut dst), 2); 65 | assert_eq!(&*dst[0], &[1, 2, 3]); 66 | assert_eq!(&*dst[1], &[4]); 67 | } 68 | 69 | { 70 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 71 | let take = chain().take(6); 72 | assert_eq!(take.chunks_vectored(&mut dst), 2); 73 | assert_eq!(&*dst[0], &[1, 2, 3]); 74 | assert_eq!(&*dst[1], &[4, 5, 6]); 75 | } 76 | 77 | { 78 | let mut dst = [std::io::IoSlice::new(&[]); 2]; 79 | let take = chain().take(7); 80 | assert_eq!(take.chunks_vectored(&mut dst), 2); 81 | assert_eq!(&*dst[0], &[1, 2, 3]); 82 | assert_eq!(&*dst[1], &[4, 5, 6]); 83 | } 84 | } 85 | --------------------------------------------------------------------------------