Coverage Report

Created: 2026-07-25 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs
Line
Count
Source
1
use core::mem::{self, ManuallyDrop, MaybeUninit};
2
use core::ops::{Deref, RangeBounds};
3
use core::ptr::NonNull;
4
use core::{cmp, fmt, hash, ptr, slice};
5
6
use alloc::{
7
    alloc::{dealloc, Layout},
8
    borrow::Borrow,
9
    boxed::Box,
10
    string::String,
11
    vec::Vec,
12
};
13
14
use crate::buf::IntoIter;
15
#[allow(unused)]
16
use crate::loom::sync::atomic::AtomicMut;
17
use crate::loom::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
18
use crate::{Buf, BytesMut};
19
20
/// A cheaply cloneable and sliceable chunk of contiguous memory.
21
///
22
/// `Bytes` is an efficient container for storing and operating on contiguous
23
/// slices of memory. It is intended for use primarily in networking code, but
24
/// could have applications elsewhere as well.
25
///
26
/// `Bytes` values facilitate zero-copy network programming by allowing multiple
27
/// `Bytes` objects to point to the same underlying memory.
28
///
29
/// `Bytes` does not have a single implementation. It is an interface, whose
30
/// exact behavior is implemented through dynamic dispatch in several underlying
31
/// implementations of `Bytes`.
32
///
33
/// All `Bytes` implementations must fulfill the following requirements:
34
/// - They are cheaply cloneable and thereby shareable between an unlimited amount
35
///   of components, for example by modifying a reference count.
36
/// - Instances can be sliced to refer to a subset of the original buffer.
37
///
38
/// ```
39
/// use bytes::Bytes;
40
///
41
/// let mut mem = Bytes::from("Hello world");
42
/// let a = mem.slice(0..5);
43
///
44
/// assert_eq!(a, "Hello");
45
///
46
/// let b = mem.split_to(6);
47
///
48
/// assert_eq!(mem, "world");
49
/// assert_eq!(b, "Hello ");
50
/// ```
51
///
52
/// # Memory layout
53
///
54
/// The `Bytes` struct itself is fairly small, limited to 4 `usize` fields used
55
/// to track information about which segment of the underlying memory the
56
/// `Bytes` handle has access to.
57
///
58
/// `Bytes` keeps both a pointer to the shared state containing the full memory
59
/// slice and a pointer to the start of the region visible by the handle.
60
/// `Bytes` also tracks the length of its view into the memory.
61
///
62
/// # Sharing
63
///
64
/// `Bytes` contains a vtable, which allows implementations of `Bytes` to define
65
/// how sharing/cloning is implemented in detail.
66
/// When `Bytes::clone()` is called, `Bytes` will call the vtable function for
67
/// cloning the backing storage in order to share it behind multiple `Bytes`
68
/// instances.
69
///
70
/// For `Bytes` implementations which refer to constant memory (e.g. created
71
/// via `Bytes::from_static()`) the cloning implementation will be a no-op.
72
///
73
/// For `Bytes` implementations which point to a reference counted shared storage
74
/// (e.g. an `Arc<[u8]>`), sharing will be implemented by increasing the
75
/// reference count.
76
///
77
/// Due to this mechanism, multiple `Bytes` instances may point to the same
78
/// shared memory region.
79
/// Each `Bytes` instance can point to different sections within that
80
/// memory region, and `Bytes` instances may or may not have overlapping views
81
/// into the memory.
82
///
83
/// The following diagram visualizes a scenario where 2 `Bytes` instances make
84
/// use of an `Arc`-based backing storage, and provide access to different views:
85
///
86
/// ```text
87
///
88
///    Arc ptrs                   ┌─────────┐
89
///    ________________________ / │ Bytes 2 │
90
///   /                           └─────────┘
91
///  /          ┌───────────┐     |         |
92
/// |_________/ │  Bytes 1  │     |         |
93
/// |           └───────────┘     |         |
94
/// |           |           | ___/ data     | tail
95
/// |      data |      tail |/              |
96
/// v           v           v               v
97
/// ┌─────┬─────┬───────────┬───────────────┬─────┐
98
/// │ Arc │     │           │               │     │
99
/// └─────┴─────┴───────────┴───────────────┴─────┘
100
/// ```
101
pub struct Bytes {
102
    ptr: *const u8,
103
    len: usize,
104
    // inlined "trait object"
105
    data: AtomicPtr<()>,
106
    vtable: &'static Vtable,
107
}
108
109
// `data` is passed by value (`*mut ()` instead of `&mut AtomicPtr<()>`)
110
// when `&mut self` or `self` is consumed.
111
// This allows the optimizer to see that the address of the `Bytes` is not
112
// captured by the indirect call, enabling further optimizations.
113
pub(crate) struct Vtable {
114
    /// fn(data, ptr, len)
115
    pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes,
116
    /// fn(data, ptr, len)
117
    ///
118
    /// `into_*` consumes the `Bytes`, returning the respective value.
119
    pub into_vec: unsafe fn(*mut (), *const u8, usize) -> Vec<u8>,
120
    pub into_mut: unsafe fn(*mut (), *const u8, usize) -> BytesMut,
121
    /// fn(data)
122
    pub is_unique: unsafe fn(&AtomicPtr<()>) -> bool,
123
    /// fn(data, ptr, len)
124
    pub drop: unsafe fn(*mut (), *const u8, usize),
125
}
126
127
impl Bytes {
128
    /// Creates a new empty `Bytes`.
129
    ///
130
    /// This will not allocate and the returned `Bytes` handle will be empty.
131
    ///
132
    /// # Examples
133
    ///
134
    /// ```
135
    /// use bytes::Bytes;
136
    ///
137
    /// let b = Bytes::new();
138
    /// assert_eq!(&b[..], b"");
139
    /// ```
140
    #[inline]
141
    #[cfg(not(all(loom, test)))]
142
23
    pub const fn new() -> Self {
143
        // Make it a named const to work around
144
        // "unsizing casts are not allowed in const fn"
145
        const EMPTY: &[u8] = &[];
146
23
        Bytes::from_static(EMPTY)
147
23
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::new
Unexecuted instantiation: <bytes::bytes::Bytes>::new
<bytes::bytes::Bytes>::new
Line
Count
Source
142
23
    pub const fn new() -> Self {
143
        // Make it a named const to work around
144
        // "unsizing casts are not allowed in const fn"
145
        const EMPTY: &[u8] = &[];
146
23
        Bytes::from_static(EMPTY)
147
23
    }
148
149
    /// Creates a new empty `Bytes`.
150
    #[cfg(all(loom, test))]
151
    pub fn new() -> Self {
152
        const EMPTY: &[u8] = &[];
153
        Bytes::from_static(EMPTY)
154
    }
155
156
    /// Creates a new `Bytes` from a static slice.
157
    ///
158
    /// The returned `Bytes` will point directly to the static slice. There is
159
    /// no allocating or copying.
160
    ///
161
    /// # Examples
162
    ///
163
    /// ```
164
    /// use bytes::Bytes;
165
    ///
166
    /// let b = Bytes::from_static(b"hello");
167
    /// assert_eq!(&b[..], b"hello");
168
    /// ```
169
    #[inline]
170
    #[cfg(not(all(loom, test)))]
171
401
    pub const fn from_static(bytes: &'static [u8]) -> Self {
172
401
        Bytes {
173
401
            ptr: bytes.as_ptr(),
174
401
            len: bytes.len(),
175
401
            data: AtomicPtr::new(ptr::null_mut()),
176
401
            vtable: &STATIC_VTABLE,
177
401
        }
178
401
    }
<bytes::bytes::Bytes>::from_static
Line
Count
Source
171
154
    pub const fn from_static(bytes: &'static [u8]) -> Self {
172
154
        Bytes {
173
154
            ptr: bytes.as_ptr(),
174
154
            len: bytes.len(),
175
154
            data: AtomicPtr::new(ptr::null_mut()),
176
154
            vtable: &STATIC_VTABLE,
177
154
        }
178
154
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::from_static
<bytes::bytes::Bytes>::from_static
Line
Count
Source
171
247
    pub const fn from_static(bytes: &'static [u8]) -> Self {
172
247
        Bytes {
173
247
            ptr: bytes.as_ptr(),
174
247
            len: bytes.len(),
175
247
            data: AtomicPtr::new(ptr::null_mut()),
176
247
            vtable: &STATIC_VTABLE,
177
247
        }
178
247
    }
179
180
    /// Creates a new `Bytes` from a static slice.
181
    #[cfg(all(loom, test))]
182
    pub fn from_static(bytes: &'static [u8]) -> Self {
183
        Bytes {
184
            ptr: bytes.as_ptr(),
185
            len: bytes.len(),
186
            data: AtomicPtr::new(ptr::null_mut()),
187
            vtable: &STATIC_VTABLE,
188
        }
189
    }
190
191
    /// Creates a new `Bytes` with length zero and the given pointer as the address.
192
216
    fn new_empty_with_ptr(ptr: *const u8) -> Self {
193
216
        debug_assert!(!ptr.is_null());
194
195
        // Detach this pointer's provenance from whichever allocation it came from, and reattach it
196
        // to the provenance of the fake ZST [u8;0] at the same address.
197
216
        let ptr = without_provenance(ptr as usize);
198
199
216
        Bytes {
200
216
            ptr,
201
216
            len: 0,
202
216
            data: AtomicPtr::new(ptr::null_mut()),
203
216
            vtable: &STATIC_VTABLE,
204
216
        }
205
216
    }
206
207
    /// Create [Bytes] with a buffer whose lifetime is controlled
208
    /// via an explicit owner.
209
    ///
210
    /// A common use case is to zero-copy construct from mapped memory.
211
    ///
212
    /// ```
213
    /// # struct File;
214
    /// #
215
    /// # impl File {
216
    /// #     pub fn open(_: &str) -> Result<Self, ()> {
217
    /// #         Ok(Self)
218
    /// #     }
219
    /// # }
220
    /// #
221
    /// # mod memmap2 {
222
    /// #     pub struct Mmap;
223
    /// #
224
    /// #     impl Mmap {
225
    /// #         pub unsafe fn map(_file: &super::File) -> Result<Self, ()> {
226
    /// #             Ok(Self)
227
    /// #         }
228
    /// #     }
229
    /// #
230
    /// #     impl AsRef<[u8]> for Mmap {
231
    /// #         fn as_ref(&self) -> &[u8] {
232
    /// #             b"buf"
233
    /// #         }
234
    /// #     }
235
    /// # }
236
    /// use bytes::Bytes;
237
    /// use memmap2::Mmap;
238
    ///
239
    /// # fn main() -> Result<(), ()> {
240
    /// let file = File::open("upload_bundle.tar.gz")?;
241
    /// let mmap = unsafe { Mmap::map(&file) }?;
242
    /// let b = Bytes::from_owner(mmap);
243
    /// # Ok(())
244
    /// # }
245
    /// ```
246
    ///
247
    /// The `owner` will be transferred to the constructed [Bytes] object, which
248
    /// will ensure it is dropped once all remaining clones of the constructed
249
    /// object are dropped. The owner will then be responsible for dropping the
250
    /// specified region of memory as part of its [Drop] implementation.
251
    ///
252
    /// Note that converting [Bytes] constructed from an owner into a [BytesMut]
253
    /// will always create a deep copy of the buffer into newly allocated memory.
254
0
    pub fn from_owner<T>(owner: T) -> Self
255
0
    where
256
0
        T: AsRef<[u8]> + Send + 'static,
257
    {
258
        // Safety & Miri:
259
        // The ownership of `owner` is first transferred to the `Owned` wrapper and `Bytes` object.
260
        // This ensures that the owner is pinned in memory, allowing us to call `.as_ref()` safely
261
        // since the lifetime of the owner is controlled by the lifetime of the new `Bytes` object,
262
        // and the lifetime of the resulting borrowed `&[u8]` matches that of the owner.
263
        // Note that this remains safe so long as we only call `.as_ref()` once.
264
        //
265
        // There are some additional special considerations here:
266
        //   * We rely on Bytes's Drop impl to clean up memory should `.as_ref()` panic.
267
        //   * Setting the `ptr` and `len` on the bytes object last (after moving the owner to
268
        //     Bytes) allows Miri checks to pass since it avoids obtaining the `&[u8]` slice
269
        //     from a stack-owned Box.
270
        // More details on this: https://github.com/tokio-rs/bytes/pull/742/#discussion_r1813375863
271
        //                  and: https://github.com/tokio-rs/bytes/pull/742/#discussion_r1813316032
272
273
0
        let owned = Box::into_raw(Box::new(Owned {
274
0
            ref_cnt: AtomicUsize::new(1),
275
0
            owner,
276
0
        }));
277
278
0
        let mut ret = Bytes {
279
0
            ptr: NonNull::dangling().as_ptr(),
280
0
            len: 0,
281
0
            data: AtomicPtr::new(owned.cast()),
282
0
            vtable: &Owned::<T>::VTABLE,
283
0
        };
284
285
0
        let buf = unsafe { &*owned }.owner.as_ref();
286
0
        ret.ptr = buf.as_ptr();
287
0
        ret.len = buf.len();
288
289
0
        ret
290
0
    }
291
292
    /// Returns the number of bytes contained in this `Bytes`.
293
    ///
294
    /// # Examples
295
    ///
296
    /// ```
297
    /// use bytes::Bytes;
298
    ///
299
    /// let b = Bytes::from(&b"hello"[..]);
300
    /// assert_eq!(b.len(), 5);
301
    /// ```
302
    #[inline]
303
929
    pub const fn len(&self) -> usize {
304
929
        self.len
305
929
    }
<bytes::bytes::Bytes>::len
Line
Count
Source
303
357
    pub const fn len(&self) -> usize {
304
357
        self.len
305
357
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::len
Unexecuted instantiation: <bytes::bytes::Bytes>::len
<bytes::bytes::Bytes>::len
Line
Count
Source
303
267
    pub const fn len(&self) -> usize {
304
267
        self.len
305
267
    }
<bytes::bytes::Bytes>::len
Line
Count
Source
303
305
    pub const fn len(&self) -> usize {
304
305
        self.len
305
305
    }
306
307
    /// Returns true if the `Bytes` has a length of 0.
308
    ///
309
    /// # Examples
310
    ///
311
    /// ```
312
    /// use bytes::Bytes;
313
    ///
314
    /// let b = Bytes::new();
315
    /// assert!(b.is_empty());
316
    /// ```
317
    #[inline]
318
0
    pub const fn is_empty(&self) -> bool {
319
0
        self.len == 0
320
0
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::is_empty
Unexecuted instantiation: <bytes::bytes::Bytes>::is_empty
321
322
    /// Returns true if this is the only reference to the data and
323
    /// `Into<BytesMut>` would avoid cloning the underlying buffer.
324
    ///
325
    /// Always returns false if the data is backed by a [static slice](Bytes::from_static),
326
    /// or an [owner](Bytes::from_owner).
327
    ///
328
    /// The result of this method may be invalidated immediately if another
329
    /// thread clones this value while this is being called. Ensure you have
330
    /// unique access to this value (`&mut Bytes`) first if you need to be
331
    /// certain the result is valid (i.e. for safety reasons).
332
    /// # Examples
333
    ///
334
    /// ```
335
    /// use bytes::Bytes;
336
    ///
337
    /// let a = Bytes::from(vec![1, 2, 3]);
338
    /// assert!(a.is_unique());
339
    /// let b = a.clone();
340
    /// assert!(!a.is_unique());
341
    /// ```
342
0
    pub fn is_unique(&self) -> bool {
343
0
        unsafe { (self.vtable.is_unique)(&self.data) }
344
0
    }
345
346
    /// Creates `Bytes` instance from slice, by copying it.
347
0
    pub fn copy_from_slice(data: &[u8]) -> Self {
348
0
        data.to_vec().into()
349
0
    }
350
351
    /// Returns a slice of self for the provided range.
352
    ///
353
    /// This will increment the reference count for the underlying memory and
354
    /// return a new `Bytes` handle set to the slice.
355
    ///
356
    /// This operation is `O(1)`.
357
    ///
358
    /// # Examples
359
    ///
360
    /// ```
361
    /// use bytes::Bytes;
362
    ///
363
    /// let a = Bytes::from(&b"hello world"[..]);
364
    /// let b = a.slice(2..5);
365
    ///
366
    /// assert_eq!(&b[..], b"llo");
367
    /// ```
368
    ///
369
    /// # Panics
370
    ///
371
    /// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing
372
    /// will panic.
373
280
    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
374
280
        let (begin, end) = crate::range(range, self.len());
375
376
280
        if end == begin {
377
216
            return Bytes::new_empty_with_ptr(self.ptr.wrapping_add(begin));
378
64
        }
379
380
64
        let mut ret = self.clone();
381
382
64
        ret.len = end - begin;
383
64
        ret.ptr = unsafe { ret.ptr.add(begin) };
384
385
64
        ret
386
280
    }
<bytes::bytes::Bytes>::slice::<core::ops::range::RangeFrom<usize>>
Line
Count
Source
373
146
    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
374
146
        let (begin, end) = crate::range(range, self.len());
375
376
146
        if end == begin {
377
110
            return Bytes::new_empty_with_ptr(self.ptr.wrapping_add(begin));
378
36
        }
379
380
36
        let mut ret = self.clone();
381
382
36
        ret.len = end - begin;
383
36
        ret.ptr = unsafe { ret.ptr.add(begin) };
384
385
36
        ret
386
146
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::slice::<core::ops::range::Range<usize>>
<bytes::bytes::Bytes>::slice::<core::ops::range::RangeFrom<usize>>
Line
Count
Source
373
134
    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
374
134
        let (begin, end) = crate::range(range, self.len());
375
376
134
        if end == begin {
377
106
            return Bytes::new_empty_with_ptr(self.ptr.wrapping_add(begin));
378
28
        }
379
380
28
        let mut ret = self.clone();
381
382
28
        ret.len = end - begin;
383
28
        ret.ptr = unsafe { ret.ptr.add(begin) };
384
385
28
        ret
386
134
    }
387
388
    /// Returns a slice of self that is equivalent to the given `subset`.
389
    ///
390
    /// When processing a `Bytes` buffer with other tools, one often gets a
391
    /// `&[u8]` which is in fact a slice of the `Bytes`, i.e. a subset of it.
392
    /// This function turns that `&[u8]` into another `Bytes`, as if one had
393
    /// called `self.slice()` with the offsets that correspond to `subset`.
394
    ///
395
    /// This operation is `O(1)`.
396
    ///
397
    /// # Examples
398
    ///
399
    /// ```
400
    /// use bytes::Bytes;
401
    ///
402
    /// let bytes = Bytes::from(&b"012345678"[..]);
403
    /// let as_slice = bytes.as_ref();
404
    /// let subset = &as_slice[2..6];
405
    /// let subslice = bytes.slice_ref(&subset);
406
    /// assert_eq!(&subslice[..], b"2345");
407
    /// ```
408
    ///
409
    /// # Panics
410
    ///
411
    /// Requires that the given `sub` slice is in fact contained within the
412
    /// `Bytes` buffer; otherwise this function will panic.
413
0
    pub fn slice_ref(&self, subset: &[u8]) -> Self {
414
        // Empty slice and empty Bytes may have their pointers reset
415
        // so explicitly allow empty slice to be a subslice of any slice.
416
0
        if subset.is_empty() {
417
0
            return Bytes::new();
418
0
        }
419
420
0
        let bytes_p = self.as_ptr() as usize;
421
0
        let bytes_len = self.len();
422
423
0
        let sub_p = subset.as_ptr() as usize;
424
0
        let sub_len = subset.len();
425
426
0
        assert!(
427
0
            sub_p >= bytes_p,
428
0
            "subset pointer ({:p}) is smaller than self pointer ({:p})",
429
0
            subset.as_ptr(),
430
0
            self.as_ptr(),
431
        );
432
0
        assert!(
433
0
            sub_p + sub_len <= bytes_p + bytes_len,
434
0
            "subset is out of bounds: self = ({:p}, {}), subset = ({:p}, {})",
435
0
            self.as_ptr(),
436
            bytes_len,
437
0
            subset.as_ptr(),
438
            sub_len,
439
        );
440
441
0
        let sub_offset = sub_p - bytes_p;
442
443
0
        self.slice(sub_offset..(sub_offset + sub_len))
444
0
    }
445
446
    /// Splits the bytes into two at the given index.
447
    ///
448
    /// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
449
    /// contains elements `[at, len)`. It's guaranteed that the memory does not
450
    /// move, that is, the address of `self` does not change, and the address of
451
    /// the returned slice is `at` bytes after that.
452
    ///
453
    /// This is an `O(1)` operation that just increases the reference count and
454
    /// sets a few indices.
455
    ///
456
    /// # Examples
457
    ///
458
    /// ```
459
    /// use bytes::Bytes;
460
    ///
461
    /// let mut a = Bytes::from(&b"hello world"[..]);
462
    /// let b = a.split_off(5);
463
    ///
464
    /// assert_eq!(&a[..], b"hello");
465
    /// assert_eq!(&b[..], b" world");
466
    /// ```
467
    ///
468
    /// # Panics
469
    ///
470
    /// Panics if `at > len`.
471
    #[must_use = "consider Bytes::truncate if you don't need the other half"]
472
0
    pub fn split_off(&mut self, at: usize) -> Self {
473
0
        if at == self.len() {
474
0
            return Bytes::new_empty_with_ptr(self.ptr.wrapping_add(at));
475
0
        }
476
477
0
        if at == 0 {
478
0
            return mem::replace(self, Bytes::new_empty_with_ptr(self.ptr));
479
0
        }
480
481
0
        assert!(
482
0
            at <= self.len(),
483
0
            "split_off out of bounds: {:?} <= {:?}",
484
            at,
485
0
            self.len(),
486
        );
487
488
0
        let mut ret = self.clone();
489
490
0
        self.len = at;
491
492
        // SAFETY: `at` has been asserted to be <= `self.len()`, and the
493
        // `at == self.len()` and `at == 0` cases were handled above.
494
0
        unsafe { ret.inc_start(at) };
495
496
0
        ret
497
0
    }
498
499
    /// Splits the bytes into two at the given index.
500
    ///
501
    /// Afterwards `self` contains elements `[at, len)`, and the returned
502
    /// `Bytes` contains elements `[0, at)`.
503
    ///
504
    /// This is an `O(1)` operation that just increases the reference count and
505
    /// sets a few indices.
506
    ///
507
    /// # Examples
508
    ///
509
    /// ```
510
    /// use bytes::Bytes;
511
    ///
512
    /// let mut a = Bytes::from(&b"hello world"[..]);
513
    /// let b = a.split_to(5);
514
    ///
515
    /// assert_eq!(&a[..], b" world");
516
    /// assert_eq!(&b[..], b"hello");
517
    /// ```
518
    ///
519
    /// # Panics
520
    ///
521
    /// Panics if `at > len`.
522
    #[must_use = "consider Bytes::advance if you don't need the other half"]
523
0
    pub fn split_to(&mut self, at: usize) -> Self {
524
0
        if at == self.len() {
525
0
            let end_ptr = self.ptr.wrapping_add(at);
526
0
            return mem::replace(self, Bytes::new_empty_with_ptr(end_ptr));
527
0
        }
528
529
0
        if at == 0 {
530
0
            return Bytes::new_empty_with_ptr(self.ptr);
531
0
        }
532
533
0
        assert!(
534
0
            at <= self.len(),
535
0
            "split_to out of bounds: {:?} <= {:?}",
536
            at,
537
0
            self.len(),
538
        );
539
540
0
        let mut ret = self.clone();
541
542
        // SAFETY: `at` has been asserted to be <= `self.len()`, and the
543
        // `at == self.len()` and `at == 0` cases were handled above.
544
0
        unsafe { self.inc_start(at) };
545
546
0
        ret.len = at;
547
0
        ret
548
0
    }
549
550
    /// Shortens the buffer, keeping the first `len` bytes and dropping the
551
    /// rest.
552
    ///
553
    /// If `len` is greater than the buffer's current length, this has no
554
    /// effect.
555
    ///
556
    /// The [split_off](`Self::split_off()`) method can emulate `truncate`, but this causes the
557
    /// excess bytes to be returned instead of dropped.
558
    ///
559
    /// # Examples
560
    ///
561
    /// ```
562
    /// use bytes::Bytes;
563
    ///
564
    /// let mut buf = Bytes::from(&b"hello world"[..]);
565
    /// buf.truncate(5);
566
    /// assert_eq!(buf, b"hello"[..]);
567
    /// ```
568
    #[inline]
569
0
    pub fn truncate(&mut self, len: usize) {
570
0
        if len < self.len {
571
            // The Vec "promotable" vtables do not store the capacity,
572
            // so we cannot truncate while using this repr. We *have* to
573
            // promote using `split_off` so the capacity can be stored.
574
0
            if self.vtable as *const Vtable == &PROMOTABLE_EVEN_VTABLE
575
0
                || self.vtable as *const Vtable == &PROMOTABLE_ODD_VTABLE
576
0
            {
577
0
                drop(self.split_off(len));
578
0
            } else {
579
0
                self.len = len;
580
0
            }
581
0
        }
582
0
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::truncate
Unexecuted instantiation: <bytes::bytes::Bytes>::truncate
583
584
    /// Clears the buffer, removing all data.
585
    ///
586
    /// # Examples
587
    ///
588
    /// ```
589
    /// use bytes::Bytes;
590
    ///
591
    /// let mut buf = Bytes::from(&b"hello world"[..]);
592
    /// buf.clear();
593
    /// assert!(buf.is_empty());
594
    /// ```
595
    #[inline]
596
0
    pub fn clear(&mut self) {
597
0
        self.truncate(0);
598
0
    }
599
600
    /// Try to convert self into `BytesMut`.
601
    ///
602
    /// If `self` is unique for the entire original buffer, this will succeed
603
    /// and return a `BytesMut` with the contents of `self` without copying.
604
    /// If `self` is not unique for the entire original buffer, this will fail
605
    /// and return self.
606
    ///
607
    /// This will also always fail if the buffer was constructed via either
608
    /// [from_owner](Bytes::from_owner) or [from_static](Bytes::from_static).
609
    ///
610
    /// # Examples
611
    ///
612
    /// ```
613
    /// use bytes::{Bytes, BytesMut};
614
    ///
615
    /// let bytes = Bytes::from(b"hello".to_vec());
616
    /// assert_eq!(bytes.try_into_mut(), Ok(BytesMut::from(&b"hello"[..])));
617
    /// ```
618
0
    pub fn try_into_mut(self) -> Result<BytesMut, Bytes> {
619
0
        if self.is_unique() {
620
0
            Ok(self.into())
621
        } else {
622
0
            Err(self)
623
        }
624
0
    }
625
626
    #[inline]
627
7.88M
    pub(crate) unsafe fn with_vtable(
628
7.88M
        ptr: *const u8,
629
7.88M
        len: usize,
630
7.88M
        data: AtomicPtr<()>,
631
7.88M
        vtable: &'static Vtable,
632
7.88M
    ) -> Bytes {
633
7.88M
        Bytes {
634
7.88M
            ptr,
635
7.88M
            len,
636
7.88M
            data,
637
7.88M
            vtable,
638
7.88M
        }
639
7.88M
    }
<bytes::bytes::Bytes>::with_vtable
Line
Count
Source
627
1.51M
    pub(crate) unsafe fn with_vtable(
628
1.51M
        ptr: *const u8,
629
1.51M
        len: usize,
630
1.51M
        data: AtomicPtr<()>,
631
1.51M
        vtable: &'static Vtable,
632
1.51M
    ) -> Bytes {
633
1.51M
        Bytes {
634
1.51M
            ptr,
635
1.51M
            len,
636
1.51M
            data,
637
1.51M
            vtable,
638
1.51M
        }
639
1.51M
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::with_vtable
<bytes::bytes::Bytes>::with_vtable
Line
Count
Source
627
137
    pub(crate) unsafe fn with_vtable(
628
137
        ptr: *const u8,
629
137
        len: usize,
630
137
        data: AtomicPtr<()>,
631
137
        vtable: &'static Vtable,
632
137
    ) -> Bytes {
633
137
        Bytes {
634
137
            ptr,
635
137
            len,
636
137
            data,
637
137
            vtable,
638
137
        }
639
137
    }
<bytes::bytes::Bytes>::with_vtable
Line
Count
Source
627
6.37M
    pub(crate) unsafe fn with_vtable(
628
6.37M
        ptr: *const u8,
629
6.37M
        len: usize,
630
6.37M
        data: AtomicPtr<()>,
631
6.37M
        vtable: &'static Vtable,
632
6.37M
    ) -> Bytes {
633
6.37M
        Bytes {
634
6.37M
            ptr,
635
6.37M
            len,
636
6.37M
            data,
637
6.37M
            vtable,
638
6.37M
        }
639
6.37M
    }
640
641
    // private
642
643
    #[inline]
644
15.7M
    fn as_slice(&self) -> &[u8] {
645
15.7M
        unsafe { slice::from_raw_parts(self.ptr, self.len) }
646
15.7M
    }
<bytes::bytes::Bytes>::as_slice
Line
Count
Source
644
3.02M
    fn as_slice(&self) -> &[u8] {
645
3.02M
        unsafe { slice::from_raw_parts(self.ptr, self.len) }
646
3.02M
    }
<bytes::bytes::Bytes>::as_slice
Line
Count
Source
644
572
    fn as_slice(&self) -> &[u8] {
645
572
        unsafe { slice::from_raw_parts(self.ptr, self.len) }
646
572
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::as_slice
Unexecuted instantiation: <bytes::bytes::Bytes>::as_slice
<bytes::bytes::Bytes>::as_slice
Line
Count
Source
644
12.7M
    fn as_slice(&self) -> &[u8] {
645
12.7M
        unsafe { slice::from_raw_parts(self.ptr, self.len) }
646
12.7M
    }
647
648
    #[inline]
649
267
    unsafe fn inc_start(&mut self, by: usize) {
650
        // should already be asserted, but debug assert for tests
651
267
        debug_assert!(self.len >= by, "internal: inc_start out of bounds");
652
267
        self.len -= by;
653
267
        self.ptr = self.ptr.add(by);
654
267
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::inc_start
Unexecuted instantiation: <bytes::bytes::Bytes>::inc_start
<bytes::bytes::Bytes>::inc_start
Line
Count
Source
649
267
    unsafe fn inc_start(&mut self, by: usize) {
650
        // should already be asserted, but debug assert for tests
651
267
        debug_assert!(self.len >= by, "internal: inc_start out of bounds");
652
267
        self.len -= by;
653
267
        self.ptr = self.ptr.add(by);
654
267
    }
Unexecuted instantiation: <bytes::bytes::Bytes>::inc_start
655
656
    #[inline]
657
7.89M
    fn data_mut(&mut self) -> *mut () {
658
7.89M
        self.data.with_mut(|p| *p)
659
7.89M
    }
660
}
661
662
// Vtable must enforce this behavior
663
unsafe impl Send for Bytes {}
664
unsafe impl Sync for Bytes {}
665
666
impl Drop for Bytes {
667
    #[inline]
668
7.89M
    fn drop(&mut self) {
669
7.89M
        let data = self.data_mut();
670
7.89M
        unsafe { (self.vtable.drop)(data, self.ptr, self.len) }
671
7.89M
    }
672
}
673
674
impl Clone for Bytes {
675
    #[inline]
676
361
    fn clone(&self) -> Bytes {
677
361
        unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) }
678
361
    }
<bytes::bytes::Bytes as core::clone::Clone>::clone
Line
Count
Source
676
58
    fn clone(&self) -> Bytes {
677
58
        unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) }
678
58
    }
<bytes::bytes::Bytes as core::clone::Clone>::clone
Line
Count
Source
676
251
    fn clone(&self) -> Bytes {
677
251
        unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) }
678
251
    }
Unexecuted instantiation: <bytes::bytes::Bytes as core::clone::Clone>::clone
Unexecuted instantiation: <bytes::bytes::Bytes as core::clone::Clone>::clone
<bytes::bytes::Bytes as core::clone::Clone>::clone
Line
Count
Source
676
52
    fn clone(&self) -> Bytes {
677
52
        unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) }
678
52
    }
679
}
680
681
impl Buf for Bytes {
682
    #[inline]
683
0
    fn remaining(&self) -> usize {
684
0
        self.len()
685
0
    }
686
687
    #[inline]
688
0
    fn chunk(&self) -> &[u8] {
689
0
        self.as_slice()
690
0
    }
691
692
    #[inline]
693
267
    fn advance(&mut self, cnt: usize) {
694
267
        assert!(
695
267
            cnt <= self.len(),
696
0
            "cannot advance past `remaining`: {:?} <= {:?}",
697
            cnt,
698
0
            self.len(),
699
        );
700
701
267
        unsafe {
702
267
            self.inc_start(cnt);
703
267
        }
704
267
    }
Unexecuted instantiation: <bytes::bytes::Bytes as bytes::buf::buf_impl::Buf>::advance
Unexecuted instantiation: <bytes::bytes::Bytes as bytes::buf::buf_impl::Buf>::advance
<bytes::bytes::Bytes as bytes::buf::buf_impl::Buf>::advance
Line
Count
Source
693
267
    fn advance(&mut self, cnt: usize) {
694
267
        assert!(
695
267
            cnt <= self.len(),
696
0
            "cannot advance past `remaining`: {:?} <= {:?}",
697
            cnt,
698
0
            self.len(),
699
        );
700
701
267
        unsafe {
702
267
            self.inc_start(cnt);
703
267
        }
704
267
    }
Unexecuted instantiation: <bytes::bytes::Bytes as bytes::buf::buf_impl::Buf>::advance
705
706
0
    fn copy_to_bytes(&mut self, len: usize) -> Self {
707
0
        self.split_to(len)
708
0
    }
709
}
710
711
impl Deref for Bytes {
712
    type Target = [u8];
713
714
    #[inline]
715
1.78k
    fn deref(&self) -> &[u8] {
716
1.78k
        self.as_slice()
717
1.78k
    }
<bytes::bytes::Bytes as core::ops::deref::Deref>::deref
Line
Count
Source
715
634
    fn deref(&self) -> &[u8] {
716
634
        self.as_slice()
717
634
    }
<bytes::bytes::Bytes as core::ops::deref::Deref>::deref
Line
Count
Source
715
572
    fn deref(&self) -> &[u8] {
716
572
        self.as_slice()
717
572
    }
Unexecuted instantiation: <bytes::bytes::Bytes as core::ops::deref::Deref>::deref
Unexecuted instantiation: <bytes::bytes::Bytes as core::ops::deref::Deref>::deref
<bytes::bytes::Bytes as core::ops::deref::Deref>::deref
Line
Count
Source
715
578
    fn deref(&self) -> &[u8] {
716
578
        self.as_slice()
717
578
    }
718
}
719
720
impl AsRef<[u8]> for Bytes {
721
    #[inline]
722
15.7M
    fn as_ref(&self) -> &[u8] {
723
15.7M
        self.as_slice()
724
15.7M
    }
<bytes::bytes::Bytes as core::convert::AsRef<[u8]>>::as_ref
Line
Count
Source
722
3.02M
    fn as_ref(&self) -> &[u8] {
723
3.02M
        self.as_slice()
724
3.02M
    }
Unexecuted instantiation: <bytes::bytes::Bytes as core::convert::AsRef<[u8]>>::as_ref
Unexecuted instantiation: <bytes::bytes::Bytes as core::convert::AsRef<[u8]>>::as_ref
Unexecuted instantiation: <bytes::bytes::Bytes as core::convert::AsRef<[u8]>>::as_ref
<bytes::bytes::Bytes as core::convert::AsRef<[u8]>>::as_ref
Line
Count
Source
722
12.7M
    fn as_ref(&self) -> &[u8] {
723
12.7M
        self.as_slice()
724
12.7M
    }
725
}
726
727
impl hash::Hash for Bytes {
728
0
    fn hash<H>(&self, state: &mut H)
729
0
    where
730
0
        H: hash::Hasher,
731
    {
732
0
        self.as_slice().hash(state);
733
0
    }
734
}
735
736
impl Borrow<[u8]> for Bytes {
737
0
    fn borrow(&self) -> &[u8] {
738
0
        self.as_slice()
739
0
    }
740
}
741
742
impl IntoIterator for Bytes {
743
    type Item = u8;
744
    type IntoIter = IntoIter<Bytes>;
745
746
0
    fn into_iter(self) -> Self::IntoIter {
747
0
        IntoIter::new(self)
748
0
    }
749
}
750
751
impl<'a> IntoIterator for &'a Bytes {
752
    type Item = &'a u8;
753
    type IntoIter = core::slice::Iter<'a, u8>;
754
755
0
    fn into_iter(self) -> Self::IntoIter {
756
0
        self.as_slice().iter()
757
0
    }
758
}
759
760
impl FromIterator<u8> for Bytes {
761
0
    fn from_iter<T: IntoIterator<Item = u8>>(into_iter: T) -> Self {
762
0
        Vec::from_iter(into_iter).into()
763
0
    }
764
}
765
766
// impl Eq
767
768
impl PartialEq for Bytes {
769
0
    fn eq(&self, other: &Bytes) -> bool {
770
0
        self.as_slice() == other.as_slice()
771
0
    }
772
}
773
774
impl PartialOrd for Bytes {
775
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
776
0
        Some(self.cmp(other))
777
0
    }
778
}
779
780
impl Ord for Bytes {
781
0
    fn cmp(&self, other: &Bytes) -> cmp::Ordering {
782
0
        self.as_slice().cmp(other.as_slice())
783
0
    }
784
}
785
786
impl Eq for Bytes {}
787
788
impl PartialEq<[u8]> for Bytes {
789
0
    fn eq(&self, other: &[u8]) -> bool {
790
0
        self.as_slice() == other
791
0
    }
792
}
793
794
impl PartialOrd<[u8]> for Bytes {
795
0
    fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
796
0
        self.as_slice().partial_cmp(other)
797
0
    }
798
}
799
800
impl PartialEq<Bytes> for [u8] {
801
0
    fn eq(&self, other: &Bytes) -> bool {
802
0
        *other == *self
803
0
    }
804
}
805
806
impl PartialOrd<Bytes> for [u8] {
807
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
808
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
809
0
    }
810
}
811
812
impl PartialEq<str> for Bytes {
813
0
    fn eq(&self, other: &str) -> bool {
814
0
        self.as_slice() == other.as_bytes()
815
0
    }
816
}
817
818
impl PartialOrd<str> for Bytes {
819
0
    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
820
0
        self.as_slice().partial_cmp(other.as_bytes())
821
0
    }
822
}
823
824
impl PartialEq<Bytes> for str {
825
0
    fn eq(&self, other: &Bytes) -> bool {
826
0
        *other == *self
827
0
    }
828
}
829
830
impl PartialOrd<Bytes> for str {
831
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
832
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
833
0
    }
834
}
835
836
impl PartialEq<Vec<u8>> for Bytes {
837
0
    fn eq(&self, other: &Vec<u8>) -> bool {
838
0
        *self == other[..]
839
0
    }
840
}
841
842
impl PartialOrd<Vec<u8>> for Bytes {
843
0
    fn partial_cmp(&self, other: &Vec<u8>) -> Option<cmp::Ordering> {
844
0
        self.as_slice().partial_cmp(&other[..])
845
0
    }
846
}
847
848
impl PartialEq<Bytes> for Vec<u8> {
849
0
    fn eq(&self, other: &Bytes) -> bool {
850
0
        *other == *self
851
0
    }
852
}
853
854
impl PartialOrd<Bytes> for Vec<u8> {
855
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
856
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
857
0
    }
858
}
859
860
impl PartialEq<String> for Bytes {
861
0
    fn eq(&self, other: &String) -> bool {
862
0
        *self == other[..]
863
0
    }
864
}
865
866
impl PartialOrd<String> for Bytes {
867
0
    fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
868
0
        self.as_slice().partial_cmp(other.as_bytes())
869
0
    }
870
}
871
872
impl PartialEq<Bytes> for String {
873
0
    fn eq(&self, other: &Bytes) -> bool {
874
0
        *other == *self
875
0
    }
876
}
877
878
impl PartialOrd<Bytes> for String {
879
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
880
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
881
0
    }
882
}
883
884
impl PartialEq<Bytes> for &[u8] {
885
0
    fn eq(&self, other: &Bytes) -> bool {
886
0
        *other == *self
887
0
    }
888
}
889
890
impl PartialOrd<Bytes> for &[u8] {
891
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
892
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
893
0
    }
894
}
895
896
impl PartialEq<Bytes> for &str {
897
0
    fn eq(&self, other: &Bytes) -> bool {
898
0
        *other == *self
899
0
    }
900
}
901
902
impl PartialOrd<Bytes> for &str {
903
0
    fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
904
0
        <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
905
0
    }
906
}
907
908
impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
909
where
910
    Bytes: PartialEq<T>,
911
{
912
0
    fn eq(&self, other: &&'a T) -> bool {
913
0
        *self == **other
914
0
    }
Unexecuted instantiation: <bytes::bytes::Bytes as core::cmp::PartialEq<&[u8]>>::eq
Unexecuted instantiation: <bytes::bytes::Bytes as core::cmp::PartialEq<&str>>::eq
915
}
916
917
impl<'a, T: ?Sized> PartialOrd<&'a T> for Bytes
918
where
919
    Bytes: PartialOrd<T>,
920
{
921
0
    fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
922
0
        self.partial_cmp(&**other)
923
0
    }
924
}
925
926
// impl From
927
928
impl Default for Bytes {
929
    #[inline]
930
0
    fn default() -> Bytes {
931
0
        Bytes::new()
932
0
    }
Unexecuted instantiation: <bytes::bytes::Bytes as core::default::Default>::default
Unexecuted instantiation: <bytes::bytes::Bytes as core::default::Default>::default
933
}
934
935
impl From<&'static [u8]> for Bytes {
936
0
    fn from(slice: &'static [u8]) -> Bytes {
937
0
        Bytes::from_static(slice)
938
0
    }
939
}
940
941
impl From<&'static str> for Bytes {
942
0
    fn from(slice: &'static str) -> Bytes {
943
0
        Bytes::from_static(slice.as_bytes())
944
0
    }
945
}
946
947
impl From<Vec<u8>> for Bytes {
948
472
    fn from(vec: Vec<u8>) -> Bytes {
949
        // Avoid an extra allocation if possible.
950
472
        if vec.len() == vec.capacity() {
951
348
            return Bytes::from(vec.into_boxed_slice());
952
124
        }
953
954
124
        let shared = Box::new(MaybeUninit::<Shared>::uninit());
955
124
        let mut vec = ManuallyDrop::new(vec);
956
124
        let ptr = vec.as_mut_ptr();
957
124
        let len = vec.len();
958
124
        let cap = vec.capacity();
959
960
124
        let shared = Shared::init_to_raw(
961
124
            shared,
962
124
            Shared {
963
124
                buf: ptr,
964
124
                cap,
965
124
                ref_cnt: AtomicUsize::new(1),
966
124
            },
967
        );
968
969
        // The pointer should be aligned, so this assert should
970
        // always succeed.
971
124
        debug_assert!(
972
0
            0 == (shared as usize & KIND_MASK),
973
0
            "internal: Box<Shared> should have an aligned pointer",
974
        );
975
124
        Bytes {
976
124
            ptr,
977
124
            len,
978
124
            data: AtomicPtr::new(shared as _),
979
124
            vtable: &SHARED_VTABLE,
980
124
        }
981
472
    }
982
}
983
984
impl From<Box<[u8]>> for Bytes {
985
348
    fn from(slice: Box<[u8]>) -> Bytes {
986
        // Box<[u8]> doesn't contain a heap allocation for empty slices,
987
        // so the pointer isn't aligned enough for the KIND_VEC stashing to
988
        // work.
989
348
        if slice.is_empty() {
990
23
            return Bytes::new();
991
325
        }
992
993
325
        let len = slice.len();
994
325
        let ptr = Box::into_raw(slice) as *mut u8;
995
996
325
        if ptr as usize & 0x1 == 0 {
997
325
            let data = ptr_map(ptr, |addr| addr | KIND_VEC);
998
325
            Bytes {
999
325
                ptr,
1000
325
                len,
1001
325
                data: AtomicPtr::new(data.cast()),
1002
325
                vtable: &PROMOTABLE_EVEN_VTABLE,
1003
325
            }
1004
        } else {
1005
0
            Bytes {
1006
0
                ptr,
1007
0
                len,
1008
0
                data: AtomicPtr::new(ptr.cast()),
1009
0
                vtable: &PROMOTABLE_ODD_VTABLE,
1010
0
            }
1011
        }
1012
348
    }
1013
}
1014
1015
impl From<Bytes> for BytesMut {
1016
    /// Convert self into `BytesMut`.
1017
    ///
1018
    /// If `bytes` is unique for the entire original buffer, this will return a
1019
    /// `BytesMut` with the contents of `bytes` without copying.
1020
    /// If `bytes` is not unique for the entire original buffer, this will make
1021
    /// a copy of `bytes` subset of the original buffer in a new `BytesMut`.
1022
    ///
1023
    /// # Examples
1024
    ///
1025
    /// ```
1026
    /// use bytes::{Bytes, BytesMut};
1027
    ///
1028
    /// let bytes = Bytes::from(b"hello".to_vec());
1029
    /// assert_eq!(BytesMut::from(bytes), BytesMut::from(&b"hello"[..]));
1030
    /// ```
1031
0
    fn from(bytes: Bytes) -> Self {
1032
0
        let mut bytes = ManuallyDrop::new(bytes);
1033
0
        let data = bytes.data_mut();
1034
0
        unsafe { (bytes.vtable.into_mut)(data, bytes.ptr, bytes.len) }
1035
0
    }
1036
}
1037
1038
impl From<String> for Bytes {
1039
126
    fn from(s: String) -> Bytes {
1040
126
        Bytes::from(s.into_bytes())
1041
126
    }
1042
}
1043
1044
impl From<Bytes> for Vec<u8> {
1045
0
    fn from(bytes: Bytes) -> Vec<u8> {
1046
0
        let mut bytes = ManuallyDrop::new(bytes);
1047
0
        let data = bytes.data_mut();
1048
0
        unsafe { (bytes.vtable.into_vec)(data, bytes.ptr, bytes.len) }
1049
0
    }
1050
}
1051
1052
// ===== impl Vtable =====
1053
1054
impl fmt::Debug for Vtable {
1055
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1056
0
        f.debug_struct("Vtable")
1057
0
            .field("clone", &(self.clone as *const ()))
1058
0
            .field("drop", &(self.drop as *const ()))
1059
0
            .finish()
1060
0
    }
1061
}
1062
1063
// ===== impl StaticVtable =====
1064
1065
const STATIC_VTABLE: Vtable = Vtable {
1066
    clone: static_clone,
1067
    into_vec: static_to_vec,
1068
    into_mut: static_to_mut,
1069
    is_unique: static_is_unique,
1070
    drop: static_drop,
1071
};
1072
1073
224
unsafe fn static_clone(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
1074
224
    let slice = slice::from_raw_parts(ptr, len);
1075
224
    Bytes::from_static(slice)
1076
224
}
1077
1078
0
unsafe fn static_to_vec(_: *mut (), ptr: *const u8, len: usize) -> Vec<u8> {
1079
0
    let slice = slice::from_raw_parts(ptr, len);
1080
0
    slice.to_vec()
1081
0
}
1082
1083
0
unsafe fn static_to_mut(_: *mut (), ptr: *const u8, len: usize) -> BytesMut {
1084
0
    let slice = slice::from_raw_parts(ptr, len);
1085
0
    BytesMut::from(slice)
1086
0
}
1087
1088
0
fn static_is_unique(_: &AtomicPtr<()>) -> bool {
1089
0
    false
1090
0
}
1091
1092
617
unsafe fn static_drop(_: *mut (), _: *const u8, _: usize) {
1093
    // nothing to drop for &'static [u8]
1094
617
}
1095
1096
// ===== impl OwnedVtable =====
1097
1098
#[repr(C)]
1099
struct Owned<T> {
1100
    ref_cnt: AtomicUsize,
1101
    owner: T,
1102
}
1103
1104
impl<T> Owned<T> {
1105
    const VTABLE: Vtable = Vtable {
1106
        clone: owned_clone::<T>,
1107
        into_vec: owned_to_vec::<T>,
1108
        into_mut: owned_to_mut::<T>,
1109
        is_unique: owned_is_unique,
1110
        drop: owned_drop::<T>,
1111
    };
1112
}
1113
1114
0
unsafe fn owned_clone<T>(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
1115
0
    let owned = data.load(Ordering::Relaxed);
1116
0
    let old_cnt = (*owned.cast::<AtomicUsize>()).fetch_add(1, Ordering::Relaxed);
1117
0
    if old_cnt > usize::MAX >> 1 {
1118
0
        crate::abort();
1119
0
    }
1120
1121
0
    Bytes {
1122
0
        ptr,
1123
0
        len,
1124
0
        data: AtomicPtr::new(owned as _),
1125
0
        vtable: &Owned::<T>::VTABLE,
1126
0
    }
1127
0
}
1128
1129
0
unsafe fn owned_to_vec<T>(owned: *mut (), ptr: *const u8, len: usize) -> Vec<u8> {
1130
0
    let slice = slice::from_raw_parts(ptr, len);
1131
0
    let vec = slice.to_vec();
1132
0
    owned_drop_impl::<T>(owned);
1133
0
    vec
1134
0
}
1135
1136
0
unsafe fn owned_to_mut<T>(owned: *mut (), ptr: *const u8, len: usize) -> BytesMut {
1137
0
    BytesMut::from_vec(owned_to_vec::<T>(owned, ptr, len))
1138
0
}
1139
1140
0
unsafe fn owned_is_unique(_data: &AtomicPtr<()>) -> bool {
1141
0
    false
1142
0
}
1143
1144
0
unsafe fn owned_drop_impl<T>(owned: *mut ()) {
1145
    {
1146
0
        let ref_cnt = &*owned.cast::<AtomicUsize>();
1147
1148
0
        let old_cnt = ref_cnt.fetch_sub(1, Ordering::Release);
1149
0
        debug_assert!(
1150
0
            old_cnt > 0 && old_cnt <= usize::MAX >> 1,
1151
0
            "expected non-zero refcount and no underflow"
1152
        );
1153
0
        if old_cnt != 1 {
1154
0
            return;
1155
0
        }
1156
0
        ref_cnt.load(Ordering::Acquire);
1157
    }
1158
1159
0
    drop(Box::<Owned<T>>::from_raw(owned.cast()));
1160
0
}
1161
1162
0
unsafe fn owned_drop<T>(data: *mut (), _ptr: *const u8, _len: usize) {
1163
0
    owned_drop_impl::<T>(data);
1164
0
}
1165
1166
// ===== impl PromotableVtable =====
1167
1168
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
1169
    clone: promotable_even_clone,
1170
    into_vec: promotable_even_to_vec,
1171
    into_mut: promotable_even_to_mut,
1172
    is_unique: promotable_is_unique,
1173
    drop: promotable_even_drop,
1174
};
1175
1176
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
1177
    clone: promotable_odd_clone,
1178
    into_vec: promotable_odd_to_vec,
1179
    into_mut: promotable_odd_to_mut,
1180
    is_unique: promotable_is_unique,
1181
    drop: promotable_odd_drop,
1182
};
1183
1184
0
unsafe fn promotable_even_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
1185
0
    let shared = data.load(Ordering::Acquire);
1186
0
    let kind = shared as usize & KIND_MASK;
1187
1188
0
    if kind == KIND_ARC {
1189
0
        shallow_clone_arc(shared.cast(), ptr, len)
1190
    } else {
1191
0
        debug_assert_eq!(kind, KIND_VEC);
1192
0
        let buf = ptr_map(shared.cast(), |addr| addr & !KIND_MASK);
1193
0
        shallow_clone_vec(data, shared, buf, ptr, len)
1194
    }
1195
0
}
1196
1197
0
unsafe fn promotable_to_vec(
1198
0
    shared: *mut (),
1199
0
    ptr: *const u8,
1200
0
    len: usize,
1201
0
    f: fn(*mut ()) -> *mut u8,
1202
0
) -> Vec<u8> {
1203
0
    let kind = shared as usize & KIND_MASK;
1204
1205
0
    if kind == KIND_ARC {
1206
0
        shared_to_vec_impl(shared.cast(), ptr, len)
1207
    } else {
1208
        // If Bytes holds a Vec, then the offset must be 0.
1209
0
        debug_assert_eq!(kind, KIND_VEC);
1210
1211
0
        let buf = f(shared);
1212
1213
0
        let cap = ptr.offset_from(buf) as usize + len;
1214
1215
        // Copy back buffer
1216
0
        ptr::copy(ptr, buf, len);
1217
1218
0
        Vec::from_raw_parts(buf, len, cap)
1219
    }
1220
0
}
1221
1222
0
unsafe fn promotable_to_mut(
1223
0
    shared: *mut (),
1224
0
    ptr: *const u8,
1225
0
    len: usize,
1226
0
    f: fn(*mut ()) -> *mut u8,
1227
0
) -> BytesMut {
1228
0
    let kind = shared as usize & KIND_MASK;
1229
1230
0
    if kind == KIND_ARC {
1231
0
        shared_to_mut_impl(shared.cast(), ptr, len)
1232
    } else {
1233
        // KIND_VEC is a view of an underlying buffer at a certain offset.
1234
        // The ptr + len always represents the end of that buffer.
1235
        // Before truncating it, it is first promoted to KIND_ARC.
1236
        // Thus, we can safely reconstruct a Vec from it without leaking memory.
1237
0
        debug_assert_eq!(kind, KIND_VEC);
1238
1239
0
        let buf = f(shared);
1240
0
        let off = ptr.offset_from(buf) as usize;
1241
0
        let cap = off + len;
1242
0
        let v = Vec::from_raw_parts(buf, cap, cap);
1243
1244
0
        let mut b = BytesMut::from_vec(v);
1245
0
        b.advance_unchecked(off);
1246
0
        b
1247
    }
1248
0
}
1249
1250
0
unsafe fn promotable_even_to_vec(shared: *mut (), ptr: *const u8, len: usize) -> Vec<u8> {
1251
0
    promotable_to_vec(shared, ptr, len, |shared| {
1252
0
        ptr_map(shared.cast(), |addr| addr & !KIND_MASK)
1253
0
    })
1254
0
}
1255
1256
0
unsafe fn promotable_even_to_mut(shared: *mut (), ptr: *const u8, len: usize) -> BytesMut {
1257
0
    promotable_to_mut(shared, ptr, len, |shared| {
1258
0
        ptr_map(shared.cast(), |addr| addr & !KIND_MASK)
1259
0
    })
1260
0
}
1261
1262
325
unsafe fn promotable_even_drop(shared: *mut (), ptr: *const u8, len: usize) {
1263
325
    let kind = shared as usize & KIND_MASK;
1264
1265
325
    if kind == KIND_ARC {
1266
0
        release_shared(shared.cast());
1267
0
    } else {
1268
325
        debug_assert_eq!(kind, KIND_VEC);
1269
325
        let buf = ptr_map(shared.cast(), |addr| addr & !KIND_MASK);
1270
325
        free_boxed_slice(buf, ptr, len);
1271
    }
1272
325
}
1273
1274
0
unsafe fn promotable_odd_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
1275
0
    let shared = data.load(Ordering::Acquire);
1276
0
    let kind = shared as usize & KIND_MASK;
1277
1278
0
    if kind == KIND_ARC {
1279
0
        shallow_clone_arc(shared as _, ptr, len)
1280
    } else {
1281
0
        debug_assert_eq!(kind, KIND_VEC);
1282
0
        shallow_clone_vec(data, shared, shared.cast(), ptr, len)
1283
    }
1284
0
}
1285
1286
0
unsafe fn promotable_odd_to_vec(shared: *mut (), ptr: *const u8, len: usize) -> Vec<u8> {
1287
0
    promotable_to_vec(shared, ptr, len, |shared| shared.cast())
1288
0
}
1289
1290
0
unsafe fn promotable_odd_to_mut(shared: *mut (), ptr: *const u8, len: usize) -> BytesMut {
1291
0
    promotable_to_mut(shared, ptr, len, |shared| shared.cast())
1292
0
}
1293
1294
0
unsafe fn promotable_odd_drop(shared: *mut (), ptr: *const u8, len: usize) {
1295
0
    let kind = shared as usize & KIND_MASK;
1296
1297
0
    if kind == KIND_ARC {
1298
0
        release_shared(shared.cast());
1299
0
    } else {
1300
0
        debug_assert_eq!(kind, KIND_VEC);
1301
1302
0
        free_boxed_slice(shared.cast(), ptr, len);
1303
    }
1304
0
}
1305
1306
0
unsafe fn promotable_is_unique(data: &AtomicPtr<()>) -> bool {
1307
0
    let shared = data.load(Ordering::Acquire);
1308
0
    let kind = shared as usize & KIND_MASK;
1309
1310
0
    if kind == KIND_ARC {
1311
0
        let ref_cnt = (*shared.cast::<Shared>()).ref_cnt.load(Ordering::Relaxed);
1312
0
        ref_cnt == 1
1313
    } else {
1314
0
        true
1315
    }
1316
0
}
1317
1318
325
unsafe fn free_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) {
1319
325
    let cap = offset.offset_from(buf) as usize + len;
1320
325
    dealloc(buf, Layout::from_size_align(cap, 1).unwrap())
1321
325
}
1322
1323
// ===== impl SharedVtable =====
1324
1325
struct Shared {
1326
    // Holds arguments to dealloc upon Drop, but otherwise doesn't use them
1327
    buf: *mut u8,
1328
    cap: usize,
1329
    ref_cnt: AtomicUsize,
1330
}
1331
1332
impl Shared {
1333
124
    fn init_to_raw(b: Box<MaybeUninit<Self>>, v: Self) -> *mut Self {
1334
124
        let shared = Box::into_raw(b).cast::<Self>();
1335
        // SAFETY: The Box has the right layout.
1336
124
        unsafe { shared.write(v) };
1337
124
        shared
1338
124
    }
1339
}
1340
1341
impl Drop for Shared {
1342
124
    fn drop(&mut self) {
1343
124
        unsafe { dealloc(self.buf, Layout::from_size_align(self.cap, 1).unwrap()) }
1344
124
    }
1345
}
1346
1347
// Assert that the alignment of `Shared` is divisible by 2.
1348
// This is a necessary invariant since we depend on allocating `Shared` a
1349
// shared object to implicitly carry the `KIND_ARC` flag in its pointer.
1350
// This flag is set when the LSB is 0.
1351
const _: [(); 0 - mem::align_of::<Shared>() % 2] = []; // Assert that the alignment of `Shared` is divisible by 2.
1352
1353
static SHARED_VTABLE: Vtable = Vtable {
1354
    clone: shared_clone,
1355
    into_vec: shared_to_vec,
1356
    into_mut: shared_to_mut,
1357
    is_unique: shared_is_unique,
1358
    drop: shared_drop,
1359
};
1360
1361
const KIND_ARC: usize = 0b0;
1362
const KIND_VEC: usize = 0b1;
1363
const KIND_MASK: usize = 0b1;
1364
1365
0
unsafe fn shared_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
1366
0
    let shared = data.load(Ordering::Relaxed);
1367
0
    shallow_clone_arc(shared as _, ptr, len)
1368
0
}
1369
1370
0
unsafe fn shared_to_vec_impl(shared: *mut Shared, ptr: *const u8, len: usize) -> Vec<u8> {
1371
    // Check that the ref_cnt is 1 (unique).
1372
    //
1373
    // If it is unique, then it is set to 0 with AcqRel fence for the same
1374
    // reason in release_shared.
1375
    //
1376
    // Otherwise, we take the other branch and call release_shared.
1377
0
    if (*shared)
1378
0
        .ref_cnt
1379
0
        .compare_exchange(1, 0, Ordering::AcqRel, Ordering::Relaxed)
1380
0
        .is_ok()
1381
    {
1382
        // Deallocate the `Shared` instance without running its destructor.
1383
0
        let shared = *Box::from_raw(shared);
1384
0
        let shared = ManuallyDrop::new(shared);
1385
0
        let buf = shared.buf;
1386
0
        let cap = shared.cap;
1387
1388
        // Copy back buffer
1389
0
        ptr::copy(ptr, buf, len);
1390
1391
0
        Vec::from_raw_parts(buf, len, cap)
1392
    } else {
1393
0
        let v = slice::from_raw_parts(ptr, len).to_vec();
1394
0
        release_shared(shared);
1395
0
        v
1396
    }
1397
0
}
1398
1399
0
unsafe fn shared_to_vec(shared: *mut (), ptr: *const u8, len: usize) -> Vec<u8> {
1400
0
    shared_to_vec_impl(shared.cast(), ptr, len)
1401
0
}
1402
1403
0
unsafe fn shared_to_mut_impl(shared: *mut Shared, ptr: *const u8, len: usize) -> BytesMut {
1404
    // The goal is to check if the current handle is the only handle
1405
    // that currently has access to the buffer. This is done by
1406
    // checking if the `ref_cnt` is currently 1.
1407
    //
1408
    // The `Acquire` ordering synchronizes with the `Release` as
1409
    // part of the `fetch_sub` in `release_shared`. The `fetch_sub`
1410
    // operation guarantees that any mutations done in other threads
1411
    // are ordered before the `ref_cnt` is decremented. As such,
1412
    // this `Acquire` will guarantee that those mutations are
1413
    // visible to the current thread.
1414
    //
1415
    // Otherwise, we take the other branch, copy the data and call `release_shared`.
1416
0
    if (*shared).ref_cnt.load(Ordering::Acquire) == 1 {
1417
        // Deallocate the `Shared` instance without running its destructor.
1418
0
        let shared = *Box::from_raw(shared);
1419
0
        let shared = ManuallyDrop::new(shared);
1420
0
        let buf = shared.buf;
1421
0
        let cap = shared.cap;
1422
1423
        // Rebuild Vec
1424
0
        let off = ptr.offset_from(buf) as usize;
1425
0
        let v = Vec::from_raw_parts(buf, len + off, cap);
1426
1427
0
        let mut b = BytesMut::from_vec(v);
1428
0
        b.advance_unchecked(off);
1429
0
        b
1430
    } else {
1431
        // Copy the data from Shared in a new Vec, then release it
1432
0
        let v = slice::from_raw_parts(ptr, len).to_vec();
1433
0
        release_shared(shared);
1434
0
        BytesMut::from_vec(v)
1435
    }
1436
0
}
1437
1438
0
unsafe fn shared_to_mut(shared: *mut (), ptr: *const u8, len: usize) -> BytesMut {
1439
0
    shared_to_mut_impl(shared.cast(), ptr, len)
1440
0
}
1441
1442
0
pub(crate) unsafe fn shared_is_unique(data: &AtomicPtr<()>) -> bool {
1443
0
    let shared = data.load(Ordering::Acquire);
1444
0
    let ref_cnt = (*shared.cast::<Shared>()).ref_cnt.load(Ordering::Relaxed);
1445
0
    ref_cnt == 1
1446
0
}
1447
1448
124
unsafe fn shared_drop(shared: *mut (), _ptr: *const u8, _len: usize) {
1449
124
    release_shared(shared.cast());
1450
124
}
1451
1452
0
unsafe fn shallow_clone_arc(shared: *mut Shared, ptr: *const u8, len: usize) -> Bytes {
1453
0
    let old_size = (*shared).ref_cnt.fetch_add(1, Ordering::Relaxed);
1454
1455
0
    if old_size > usize::MAX >> 1 {
1456
0
        crate::abort();
1457
0
    }
1458
1459
0
    Bytes {
1460
0
        ptr,
1461
0
        len,
1462
0
        data: AtomicPtr::new(shared as _),
1463
0
        vtable: &SHARED_VTABLE,
1464
0
    }
1465
0
}
1466
1467
#[cold]
1468
0
unsafe fn shallow_clone_vec(
1469
0
    atom: &AtomicPtr<()>,
1470
0
    ptr: *const (),
1471
0
    buf: *mut u8,
1472
0
    offset: *const u8,
1473
0
    len: usize,
1474
0
) -> Bytes {
1475
    // If the buffer is still tracked in a `Vec<u8>`. It is time to
1476
    // promote the vec to an `Arc`. This could potentially be called
1477
    // concurrently, so some care must be taken.
1478
1479
    // First, allocate a new `Shared` instance containing the
1480
    // `Vec` fields. It's important to note that `ptr`, `len`,
1481
    // and `cap` cannot be mutated without having `&mut self`.
1482
    // This means that these fields will not be concurrently
1483
    // updated and since the buffer hasn't been promoted to an
1484
    // `Arc`, those three fields still are the components of the
1485
    // vector.
1486
0
    let shared = Box::new(MaybeUninit::<Shared>::uninit());
1487
0
    let shared = Shared::init_to_raw(
1488
0
        shared,
1489
0
        Shared {
1490
0
            buf,
1491
0
            cap: offset.offset_from(buf) as usize + len,
1492
0
            // Initialize refcount to 2. One for this reference, and one
1493
0
            // for the new clone that will be returned from
1494
0
            // `shallow_clone`.
1495
0
            ref_cnt: AtomicUsize::new(2),
1496
0
        },
1497
    );
1498
1499
    // The pointer should be aligned, so this assert should
1500
    // always succeed.
1501
0
    debug_assert!(
1502
0
        0 == (shared as usize & KIND_MASK),
1503
0
        "internal: Box<Shared> should have an aligned pointer",
1504
    );
1505
1506
    // Try compare & swapping the pointer into the `arc` field.
1507
    // `Release` is used synchronize with other threads that
1508
    // will load the `arc` field.
1509
    //
1510
    // If the `compare_exchange` fails, then the thread lost the
1511
    // race to promote the buffer to shared. The `Acquire`
1512
    // ordering will synchronize with the `compare_exchange`
1513
    // that happened in the other thread and the `Shared`
1514
    // pointed to by `actual` will be visible.
1515
0
    match atom.compare_exchange(ptr as _, shared as _, Ordering::AcqRel, Ordering::Acquire) {
1516
0
        Ok(actual) => {
1517
0
            debug_assert!(core::ptr::eq(actual, ptr));
1518
            // The upgrade was successful, the new handle can be
1519
            // returned.
1520
0
            Bytes {
1521
0
                ptr: offset,
1522
0
                len,
1523
0
                data: AtomicPtr::new(shared as _),
1524
0
                vtable: &SHARED_VTABLE,
1525
0
            }
1526
        }
1527
0
        Err(actual) => {
1528
            // The upgrade failed, a concurrent clone happened. Release
1529
            // the allocation that was made in this thread, it will not
1530
            // be needed.
1531
0
            let shared = Box::from_raw(shared);
1532
0
            mem::forget(*shared);
1533
1534
            // Buffer already promoted to shared storage, so increment ref
1535
            // count.
1536
0
            shallow_clone_arc(actual as _, offset, len)
1537
        }
1538
    }
1539
0
}
1540
1541
124
unsafe fn release_shared(ptr: *mut Shared) {
1542
    // `Shared` storage... follow the drop steps from Arc.
1543
124
    if (*ptr).ref_cnt.fetch_sub(1, Ordering::Release) != 1 {
1544
0
        return;
1545
124
    }
1546
1547
    // This fence is needed to prevent reordering of use of the data and
1548
    // deletion of the data.  Because it is marked `Release`, the decreasing
1549
    // of the reference count synchronizes with this `Acquire` fence. This
1550
    // means that use of the data happens before decreasing the reference
1551
    // count, which happens before this fence, which happens before the
1552
    // deletion of the data.
1553
    //
1554
    // As explained in the [Boost documentation][1],
1555
    //
1556
    // > It is important to enforce any possible access to the object in one
1557
    // > thread (through an existing reference) to *happen before* deleting
1558
    // > the object in a different thread. This is achieved by a "release"
1559
    // > operation after dropping a reference (any access to the object
1560
    // > through this reference must obviously happened before), and an
1561
    // > "acquire" operation before deleting the object.
1562
    //
1563
    // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
1564
    //
1565
    // Thread sanitizer does not support atomic fences. Use an atomic load
1566
    // instead.
1567
124
    (*ptr).ref_cnt.load(Ordering::Acquire);
1568
1569
    // Drop the data
1570
124
    drop(Box::from_raw(ptr));
1571
124
}
1572
1573
// Ideally we would always use this version of `ptr_map` since it is strict
1574
// provenance compatible, but it results in worse codegen. We will however still
1575
// use it on miri because it gives better diagnostics for people who test bytes
1576
// code with miri.
1577
//
1578
// See https://github.com/tokio-rs/bytes/pull/545 for more info.
1579
#[cfg(miri)]
1580
fn ptr_map<F>(ptr: *mut u8, f: F) -> *mut u8
1581
where
1582
    F: FnOnce(usize) -> usize,
1583
{
1584
    let old_addr = ptr as usize;
1585
    let new_addr = f(old_addr);
1586
    let diff = new_addr.wrapping_sub(old_addr);
1587
    ptr.wrapping_add(diff)
1588
}
1589
1590
#[cfg(not(miri))]
1591
650
fn ptr_map<F>(ptr: *mut u8, f: F) -> *mut u8
1592
650
where
1593
650
    F: FnOnce(usize) -> usize,
1594
{
1595
650
    let old_addr = ptr as usize;
1596
650
    let new_addr = f(old_addr);
1597
650
    new_addr as *mut u8
1598
650
}
Unexecuted instantiation: bytes::bytes::ptr_map::<bytes::bytes::promotable_even_to_mut::{closure#0}::{closure#0}>
Unexecuted instantiation: bytes::bytes::ptr_map::<bytes::bytes::promotable_even_to_vec::{closure#0}::{closure#0}>
bytes::bytes::ptr_map::<bytes::bytes::promotable_even_drop::{closure#0}>
Line
Count
Source
1591
325
fn ptr_map<F>(ptr: *mut u8, f: F) -> *mut u8
1592
325
where
1593
325
    F: FnOnce(usize) -> usize,
1594
{
1595
325
    let old_addr = ptr as usize;
1596
325
    let new_addr = f(old_addr);
1597
325
    new_addr as *mut u8
1598
325
}
Unexecuted instantiation: bytes::bytes::ptr_map::<bytes::bytes::promotable_even_clone::{closure#0}>
bytes::bytes::ptr_map::<<bytes::bytes::Bytes as core::convert::From<alloc::boxed::Box<[u8]>>>::from::{closure#0}>
Line
Count
Source
1591
325
fn ptr_map<F>(ptr: *mut u8, f: F) -> *mut u8
1592
325
where
1593
325
    F: FnOnce(usize) -> usize,
1594
{
1595
325
    let old_addr = ptr as usize;
1596
325
    let new_addr = f(old_addr);
1597
325
    new_addr as *mut u8
1598
325
}
1599
1600
216
fn without_provenance(ptr: usize) -> *const u8 {
1601
216
    core::ptr::null::<u8>().wrapping_add(ptr)
1602
216
}
1603
1604
// compile-fails
1605
1606
/// ```compile_fail
1607
/// use bytes::Bytes;
1608
/// #[deny(unused_must_use)]
1609
/// {
1610
///     let mut b1 = Bytes::from("hello world");
1611
///     b1.split_to(6);
1612
/// }
1613
/// ```
1614
0
fn _split_to_must_use() {}
1615
1616
/// ```compile_fail
1617
/// use bytes::Bytes;
1618
/// #[deny(unused_must_use)]
1619
/// {
1620
///     let mut b1 = Bytes::from("hello world");
1621
///     b1.split_off(6);
1622
/// }
1623
/// ```
1624
0
fn _split_off_must_use() {}
1625
1626
// fuzz tests
1627
#[cfg(all(test, loom))]
1628
mod fuzz {
1629
    use loom::sync::Arc;
1630
    use loom::thread;
1631
1632
    use super::Bytes;
1633
    #[test]
1634
    fn bytes_cloning_vec() {
1635
        loom::model(|| {
1636
            let a = Bytes::from(b"abcdefgh".to_vec());
1637
            let addr = a.as_ptr() as usize;
1638
1639
            // test the Bytes::clone is Sync by putting it in an Arc
1640
            let a1 = Arc::new(a);
1641
            let a2 = a1.clone();
1642
1643
            let t1 = thread::spawn(move || {
1644
                let b: Bytes = (*a1).clone();
1645
                assert_eq!(b.as_ptr() as usize, addr);
1646
            });
1647
1648
            let t2 = thread::spawn(move || {
1649
                let b: Bytes = (*a2).clone();
1650
                assert_eq!(b.as_ptr() as usize, addr);
1651
            });
1652
1653
            t1.join().unwrap();
1654
            t2.join().unwrap();
1655
        });
1656
    }
1657
}