Skip to content

Commit 4020841

Browse files
committed
add will_truncate to Bytes vtable to prevent special casing promotable ones
1 parent 21dd996 commit 4020841

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

src/bytes.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ pub(crate) struct Vtable {
110110
pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes,
111111
/// fn(data, ptr, len)
112112
///
113+
/// Called before the `Bytes::truncate` is processed.
114+
/// Useful if the implementation needs some preparation step for it.
115+
pub will_truncate: unsafe fn(&mut AtomicPtr<()>, *const u8, usize),
116+
/// fn(data, ptr, len)
117+
///
113118
/// Consumes `Bytes` to return `Vec<u8>`
114119
pub into_vec: unsafe fn(&mut AtomicPtr<()>, *const u8, usize) -> Vec<u8>,
115120
/// fn(data, ptr, len)
@@ -455,16 +460,10 @@ impl Bytes {
455460
#[inline]
456461
pub fn truncate(&mut self, len: usize) {
457462
if len < self.len {
458-
// The Vec "promotable" vtables do not store the capacity,
459-
// so we cannot truncate while using this repr. We *have* to
460-
// promote using `split_off` so the capacity can be stored.
461-
if self.vtable as *const Vtable == &PROMOTABLE_EVEN_VTABLE
462-
|| self.vtable as *const Vtable == &PROMOTABLE_ODD_VTABLE
463-
{
464-
drop(self.split_off(len));
465-
} else {
466-
self.len = len;
463+
unsafe {
464+
(self.vtable.will_truncate)(&mut self.data, self.ptr, self.len);
467465
}
466+
self.len = len;
468467
}
469468
}
470469

@@ -862,6 +861,7 @@ impl fmt::Debug for Vtable {
862861
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
863862
f.debug_struct("Vtable")
864863
.field("clone", &(self.clone as *const ()))
864+
.field("will_truncate", &(self.will_truncate as *const ()))
865865
.field("into_vec", &(self.into_vec as *const ()))
866866
.field("drop", &(self.drop as *const ()))
867867
.finish()
@@ -872,6 +872,7 @@ impl fmt::Debug for Vtable {
872872

873873
const STATIC_VTABLE: Vtable = Vtable {
874874
clone: static_clone,
875+
will_truncate: static_will_truncate,
875876
into_vec: static_into_vec,
876877
drop: static_drop,
877878
};
@@ -881,6 +882,10 @@ unsafe fn static_clone(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
881882
Bytes::from_static(slice)
882883
}
883884

885+
unsafe fn static_will_truncate(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
886+
// nothing to do before truncate for &'static [u8]
887+
}
888+
884889
unsafe fn static_into_vec(_: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
885890
let slice = slice::from_raw_parts(ptr, len);
886891
slice.to_vec()
@@ -894,12 +899,14 @@ unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
894899

895900
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
896901
clone: promotable_even_clone,
902+
will_truncate: promotable_even_will_truncate,
897903
into_vec: promotable_even_into_vec,
898904
drop: promotable_even_drop,
899905
};
900906

901907
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
902908
clone: promotable_odd_clone,
909+
will_truncate: promotable_odd_will_truncate,
903910
into_vec: promotable_odd_into_vec,
904911
drop: promotable_odd_drop,
905912
};
@@ -917,6 +924,13 @@ unsafe fn promotable_even_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize
917924
}
918925
}
919926

927+
unsafe fn promotable_even_will_truncate(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) {
928+
// The Vec "promotable" vtables do not store the capacity,
929+
// so we cannot truncate while using this repr. We *have* to
930+
// promote using `clone` so the capacity can be stored.
931+
drop(promotable_even_clone(&*data, ptr, len));
932+
}
933+
920934
unsafe fn promotable_into_vec(
921935
data: &mut AtomicPtr<()>,
922936
ptr: *const u8,
@@ -980,6 +994,13 @@ unsafe fn promotable_odd_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize)
980994
}
981995
}
982996

997+
unsafe fn promotable_odd_will_truncate(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) {
998+
// The Vec "promotable" vtables do not store the capacity,
999+
// so we cannot truncate while using this repr. We *have* to
1000+
// promote using `clone` so the capacity can be stored.
1001+
drop(promotable_odd_clone(&*data, ptr, len));
1002+
}
1003+
9831004
unsafe fn promotable_odd_into_vec(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
9841005
promotable_into_vec(data, ptr, len, |shared| shared.cast())
9851006
}
@@ -1027,6 +1048,7 @@ const _: [(); 0 - mem::align_of::<Shared>() % 2] = []; // Assert that the alignm
10271048

10281049
static SHARED_VTABLE: Vtable = Vtable {
10291050
clone: shared_clone,
1051+
will_truncate: shared_will_truncate,
10301052
into_vec: shared_into_vec,
10311053
drop: shared_drop,
10321054
};
@@ -1040,6 +1062,10 @@ unsafe fn shared_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Byte
10401062
shallow_clone_arc(shared as _, ptr, len)
10411063
}
10421064

1065+
unsafe fn shared_will_truncate(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
1066+
// nothing to do before truncate for Shared
1067+
}
1068+
10431069
unsafe fn shared_into_vec_impl(shared: *mut Shared, ptr: *const u8, len: usize) -> Vec<u8> {
10441070
// Check that the ref_cnt is 1 (unique).
10451071
//

src/bytes_mut.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,7 @@ unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize)
16751675

16761676
static SHARED_VTABLE: Vtable = Vtable {
16771677
clone: shared_v_clone,
1678+
will_truncate: shared_v_will_truncate,
16781679
into_vec: shared_v_into_vec,
16791680
drop: shared_v_drop,
16801681
};
@@ -1687,6 +1688,10 @@ unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> By
16871688
Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE)
16881689
}
16891690

1691+
unsafe fn shared_v_will_truncate(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
1692+
// nothing to do before truncate for Shared
1693+
}
1694+
16901695
unsafe fn shared_v_into_vec(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
16911696
let shared: *mut Shared = (data.with_mut(|p| *p)).cast();
16921697

0 commit comments

Comments
 (0)