mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-26 00:00:20 +02:00
add Bytes::is_unique (#643)
This commit is contained in:
@@ -112,6 +112,8 @@ pub(crate) struct Vtable {
|
|||||||
///
|
///
|
||||||
/// takes `Bytes` to value
|
/// takes `Bytes` to value
|
||||||
pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec<u8>,
|
pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec<u8>,
|
||||||
|
/// fn(data)
|
||||||
|
pub is_unique: unsafe fn(&AtomicPtr<()>) -> bool,
|
||||||
/// fn(data, ptr, len)
|
/// fn(data, ptr, len)
|
||||||
pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize),
|
pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize),
|
||||||
}
|
}
|
||||||
@@ -208,6 +210,28 @@ impl Bytes {
|
|||||||
self.len == 0
|
self.len == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this is the only reference to the data.
|
||||||
|
///
|
||||||
|
/// Always returns false if the data is backed by a static slice.
|
||||||
|
///
|
||||||
|
/// The result of this method may be invalidated immediately if another
|
||||||
|
/// thread clones this value while this is being called. Ensure you have
|
||||||
|
/// unique access to this value (`&mut Bytes`) first if you need to be
|
||||||
|
/// certain the result is valid (i.e. for safety reasons)
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use bytes::Bytes;
|
||||||
|
///
|
||||||
|
/// let a = Bytes::from(vec![1, 2, 3]);
|
||||||
|
/// assert!(a.is_unique());
|
||||||
|
/// let b = a.clone();
|
||||||
|
/// assert!(!a.is_unique());
|
||||||
|
/// ```
|
||||||
|
pub fn is_unique(&self) -> bool {
|
||||||
|
unsafe { (self.vtable.is_unique)(&self.data) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates `Bytes` instance from slice, by copying it.
|
/// Creates `Bytes` instance from slice, by copying it.
|
||||||
pub fn copy_from_slice(data: &[u8]) -> Self {
|
pub fn copy_from_slice(data: &[u8]) -> Self {
|
||||||
data.to_vec().into()
|
data.to_vec().into()
|
||||||
@@ -898,6 +922,7 @@ impl fmt::Debug for Vtable {
|
|||||||
const STATIC_VTABLE: Vtable = Vtable {
|
const STATIC_VTABLE: Vtable = Vtable {
|
||||||
clone: static_clone,
|
clone: static_clone,
|
||||||
to_vec: static_to_vec,
|
to_vec: static_to_vec,
|
||||||
|
is_unique: static_is_unique,
|
||||||
drop: static_drop,
|
drop: static_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -911,6 +936,10 @@ unsafe fn static_to_vec(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8
|
|||||||
slice.to_vec()
|
slice.to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn static_is_unique(_: &AtomicPtr<()>) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
|
unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
|
||||||
// nothing to drop for &'static [u8]
|
// nothing to drop for &'static [u8]
|
||||||
}
|
}
|
||||||
@@ -920,12 +949,14 @@ unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
|
|||||||
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
|
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
|
||||||
clone: promotable_even_clone,
|
clone: promotable_even_clone,
|
||||||
to_vec: promotable_even_to_vec,
|
to_vec: promotable_even_to_vec,
|
||||||
|
is_unique: promotable_is_unique,
|
||||||
drop: promotable_even_drop,
|
drop: promotable_even_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
|
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
|
||||||
clone: promotable_odd_clone,
|
clone: promotable_odd_clone,
|
||||||
to_vec: promotable_odd_to_vec,
|
to_vec: promotable_odd_to_vec,
|
||||||
|
is_unique: promotable_is_unique,
|
||||||
drop: promotable_odd_drop,
|
drop: promotable_odd_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1020,6 +1051,18 @@ unsafe fn promotable_odd_drop(data: &mut AtomicPtr<()>, ptr: *const u8, len: usi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn promotable_is_unique(data: &AtomicPtr<()>) -> bool {
|
||||||
|
let shared = data.load(Ordering::Acquire);
|
||||||
|
let kind = shared as usize & KIND_MASK;
|
||||||
|
|
||||||
|
if kind == KIND_ARC {
|
||||||
|
let ref_cnt = (*shared.cast::<Shared>()).ref_cnt.load(Ordering::Relaxed);
|
||||||
|
ref_cnt == 1
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn free_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) {
|
unsafe fn free_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) {
|
||||||
let cap = (offset as usize - buf as usize) + len;
|
let cap = (offset as usize - buf as usize) + len;
|
||||||
dealloc(buf, Layout::from_size_align(cap, 1).unwrap())
|
dealloc(buf, Layout::from_size_align(cap, 1).unwrap())
|
||||||
@@ -1049,6 +1092,7 @@ const _: [(); 0 - mem::align_of::<Shared>() % 2] = []; // Assert that the alignm
|
|||||||
static SHARED_VTABLE: Vtable = Vtable {
|
static SHARED_VTABLE: Vtable = Vtable {
|
||||||
clone: shared_clone,
|
clone: shared_clone,
|
||||||
to_vec: shared_to_vec,
|
to_vec: shared_to_vec,
|
||||||
|
is_unique: shared_is_unique,
|
||||||
drop: shared_drop,
|
drop: shared_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1094,6 +1138,12 @@ unsafe fn shared_to_vec(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec
|
|||||||
shared_to_vec_impl(data.load(Ordering::Relaxed).cast(), ptr, len)
|
shared_to_vec_impl(data.load(Ordering::Relaxed).cast(), ptr, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn shared_is_unique(data: &AtomicPtr<()>) -> bool {
|
||||||
|
let shared = data.load(Ordering::Acquire);
|
||||||
|
let ref_cnt = (*shared.cast::<Shared>()).ref_cnt.load(Ordering::Relaxed);
|
||||||
|
ref_cnt == 1
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn shared_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
unsafe fn shared_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
||||||
data.with_mut(|shared| {
|
data.with_mut(|shared| {
|
||||||
release_shared(shared.cast());
|
release_shared(shared.cast());
|
||||||
|
|||||||
@@ -1708,6 +1708,7 @@ unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize)
|
|||||||
static SHARED_VTABLE: Vtable = Vtable {
|
static SHARED_VTABLE: Vtable = Vtable {
|
||||||
clone: shared_v_clone,
|
clone: shared_v_clone,
|
||||||
to_vec: shared_v_to_vec,
|
to_vec: shared_v_to_vec,
|
||||||
|
is_unique: crate::bytes::shared_is_unique,
|
||||||
drop: shared_v_drop,
|
drop: shared_v_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1208,3 +1208,36 @@ fn test_bytes_capacity_len() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn static_is_unique() {
|
||||||
|
let b = Bytes::from_static(LONG);
|
||||||
|
assert!(!b.is_unique());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_is_unique() {
|
||||||
|
let v: Vec<u8> = LONG.to_vec();
|
||||||
|
let b = Bytes::from(v);
|
||||||
|
assert!(b.is_unique());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arc_is_unique() {
|
||||||
|
let v: Vec<u8> = LONG.to_vec();
|
||||||
|
let b = Bytes::from(v);
|
||||||
|
let c = b.clone();
|
||||||
|
assert!(!b.is_unique());
|
||||||
|
drop(c);
|
||||||
|
assert!(b.is_unique());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shared_is_unique() {
|
||||||
|
let v: Vec<u8> = LONG.to_vec();
|
||||||
|
let b = Bytes::from(v);
|
||||||
|
let c = b.clone();
|
||||||
|
assert!(!c.is_unique());
|
||||||
|
drop(b);
|
||||||
|
assert!(c.is_unique());
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user