aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Cyborus04 <cyborus@cyborus.xyz> 2024-01-19 17:59:30 -0500
committerGravatar GitHub <noreply@github.com> 2024-01-19 23:59:30 +0100
commit0864aea9704ac12fa53ee96a7f968e51c9dabba1 (patch)
tree325dfc2f046df75116b9157889c0d7f18ffdea95 /src
parentabb4a2e66cab68a6d1deb3d37377625443794cfd (diff)
downloadbytes-0864aea9704ac12fa53ee96a7f968e51c9dabba1.tar.gz
bytes-0864aea9704ac12fa53ee96a7f968e51c9dabba1.tar.zst
bytes-0864aea9704ac12fa53ee96a7f968e51c9dabba1.zip
add `Bytes::is_unique` (#643)
Diffstat (limited to 'src')
-rw-r--r--src/bytes.rs50
-rw-r--r--src/bytes_mut.rs1
2 files changed, 51 insertions, 0 deletions
diff --git a/src/bytes.rs b/src/bytes.rs
index 9fed3d2..9eda9f4 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -112,6 +112,8 @@ pub(crate) struct Vtable {
///
/// takes `Bytes` to value
pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec<u8>,
+ /// fn(data)
+ pub is_unique: unsafe fn(&AtomicPtr<()>) -> bool,
/// fn(data, ptr, len)
pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize),
}
@@ -208,6 +210,28 @@ impl Bytes {
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.
pub fn copy_from_slice(data: &[u8]) -> Self {
data.to_vec().into()
@@ -898,6 +922,7 @@ impl fmt::Debug for Vtable {
const STATIC_VTABLE: Vtable = Vtable {
clone: static_clone,
to_vec: static_to_vec,
+ is_unique: static_is_unique,
drop: static_drop,
};
@@ -911,6 +936,10 @@ unsafe fn static_to_vec(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8
slice.to_vec()
}
+fn static_is_unique(_: &AtomicPtr<()>) -> bool {
+ false
+}
+
unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
// 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 {
clone: promotable_even_clone,
to_vec: promotable_even_to_vec,
+ is_unique: promotable_is_unique,
drop: promotable_even_drop,
};
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
clone: promotable_odd_clone,
to_vec: promotable_odd_to_vec,
+ is_unique: promotable_is_unique,
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) {
let cap = (offset as usize - buf as usize) + len;
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 {
clone: shared_clone,
to_vec: shared_to_vec,
+ is_unique: shared_is_unique,
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)
}
+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) {
data.with_mut(|shared| {
release_shared(shared.cast());
diff --git a/src/bytes_mut.rs b/src/bytes_mut.rs
index dd4ff50..88d596c 100644
--- a/src/bytes_mut.rs
+++ b/src/bytes_mut.rs
@@ -1708,6 +1708,7 @@ unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize)
static SHARED_VTABLE: Vtable = Vtable {
clone: shared_v_clone,
to_vec: shared_v_to_vec,
+ is_unique: crate::bytes::shared_is_unique,
drop: shared_v_drop,
};