Skip to content

Commit 95a7229

Browse files
committed
add Bytes::downcast_impl to extract underlying implementation
1 parent 6489bb1 commit 95a7229

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/bytes.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::any::TypeId;
12
use core::iter::FromIterator;
23
use core::ops::{Deref, RangeBounds};
34
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
@@ -114,6 +115,9 @@ pub unsafe trait BytesImpl: 'static {
114115
/// Decompose `Self` into parts used by `Bytes`.
115116
fn into_bytes_parts(this: Self) -> (AtomicPtr<()>, *const u8, usize);
116117

118+
/// Creates itself directly from the raw bytes parts decomposed with `into_bytes_parts`.
119+
unsafe fn from_bytes_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self;
120+
117121
/// Returns new `Bytes` based on the current parts.
118122
unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes;
119123

@@ -132,6 +136,7 @@ pub unsafe trait BytesImpl: 'static {
132136
}
133137

134138
struct Vtable {
139+
type_id: fn() -> TypeId,
135140
/// fn(data, ptr, len)
136141
clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes,
137142
/// fn(data, ptr, len)
@@ -192,6 +197,7 @@ impl Bytes {
192197
#[cfg(not(all(loom, test)))]
193198
pub const fn from_static(bytes: &'static [u8]) -> Bytes {
194199
const STATIC_VTABLE: Vtable = Vtable {
200+
type_id: TypeId::of::<StaticImpl>,
195201
clone: <StaticImpl as BytesImpl>::clone,
196202
will_truncate: <StaticImpl as BytesImpl>::will_truncate,
197203
into_vec: <StaticImpl as BytesImpl>::into_vec,
@@ -209,6 +215,7 @@ impl Bytes {
209215
#[cfg(all(loom, test))]
210216
pub fn from_static(bytes: &'static [u8]) -> Bytes {
211217
const STATIC_VTABLE: Vtable = Vtable {
218+
type_id: TypeId::of::<StaticImpl>,
212219
clone: <StaticImpl as BytesImpl>::clone,
213220
will_truncate: <StaticImpl as BytesImpl>::will_truncate,
214221
into_vec: <StaticImpl as BytesImpl>::into_vec,
@@ -235,6 +242,7 @@ impl Bytes {
235242
len,
236243
data,
237244
vtable: &Vtable {
245+
type_id: TypeId::of::<T>,
238246
clone: T::clone,
239247
will_truncate: T::will_truncate,
240248
into_vec: T::into_vec,
@@ -543,6 +551,19 @@ impl Bytes {
543551
self.truncate(0);
544552
}
545553

554+
/// Downcast this `Bytes` into its underlying implementation.
555+
#[inline]
556+
pub fn downcast_impl<T: BytesImpl>(self) -> Result<T, Bytes> {
557+
if TypeId::of::<T>() == (self.vtable.type_id)() {
558+
Ok(unsafe {
559+
let this = &mut *mem::ManuallyDrop::new(self);
560+
T::from_bytes_parts(&mut this.data, this.ptr, this.len)
561+
})
562+
} else {
563+
Err(self)
564+
}
565+
}
566+
546567
// private
547568

548569
#[inline]
@@ -891,6 +912,7 @@ impl From<Bytes> for Vec<u8> {
891912
impl fmt::Debug for Vtable {
892913
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
893914
f.debug_struct("Vtable")
915+
.field("type_id", &self.type_id)
894916
.field("clone", &(self.clone as *const ()))
895917
.field("will_truncate", &(self.will_truncate as *const ()))
896918
.field("into_vec", &(self.into_vec as *const ()))
@@ -909,6 +931,10 @@ unsafe impl BytesImpl for StaticImpl {
909931
(mem::take(&mut bytes.data), bytes.ptr, bytes.len)
910932
}
911933

934+
unsafe fn from_bytes_parts(_data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
935+
StaticImpl(slice::from_raw_parts(ptr, len))
936+
}
937+
912938
unsafe fn clone(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
913939
let slice = slice::from_raw_parts(ptr, len);
914940
Bytes::from_static(slice)
@@ -932,7 +958,6 @@ struct PromotableOddImpl(Promotable);
932958

933959
enum Promotable {
934960
Owned(Box<[u8]>),
935-
#[allow(dead_code)]
936961
Shared(SharedImpl),
937962
}
938963

@@ -952,6 +977,12 @@ unsafe impl BytesImpl for PromotableEvenImpl {
952977
(AtomicPtr::new(data.cast()), ptr, len)
953978
}
954979

980+
unsafe fn from_bytes_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
981+
PromotableEvenImpl(promotable_from_bytes_parts(data, ptr, len, |shared| {
982+
ptr_map(shared.cast(), |addr| addr & !KIND_MASK)
983+
}))
984+
}
985+
955986
unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
956987
let shared = data.load(Ordering::Acquire);
957988
let kind = shared as usize & KIND_MASK;
@@ -994,6 +1025,30 @@ unsafe impl BytesImpl for PromotableEvenImpl {
9941025
}
9951026
}
9961027

1028+
unsafe fn promotable_from_bytes_parts(
1029+
data: &mut AtomicPtr<()>,
1030+
ptr: *const u8,
1031+
len: usize,
1032+
f: fn(*mut ()) -> *mut u8,
1033+
) -> Promotable {
1034+
let shared = *data.get_mut();
1035+
let kind = shared as usize & KIND_MASK;
1036+
1037+
if kind == KIND_ARC {
1038+
Promotable::Shared(SharedImpl::from_bytes_parts(data, ptr, len))
1039+
} else {
1040+
debug_assert_eq!(kind, KIND_VEC);
1041+
1042+
let buf = f(shared);
1043+
1044+
let cap = (ptr as usize - buf as usize) + len;
1045+
1046+
let vec = Vec::from_raw_parts(buf, cap, cap);
1047+
1048+
Promotable::Owned(vec.into_boxed_slice())
1049+
}
1050+
}
1051+
9971052
unsafe fn promotable_into_vec(
9981053
data: &mut AtomicPtr<()>,
9991054
ptr: *const u8,
@@ -1034,6 +1089,12 @@ unsafe impl BytesImpl for PromotableOddImpl {
10341089
(AtomicPtr::new(ptr.cast()), ptr, len)
10351090
}
10361091

1092+
unsafe fn from_bytes_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
1093+
PromotableOddImpl(promotable_from_bytes_parts(data, ptr, len, |shared| {
1094+
shared.cast()
1095+
}))
1096+
}
1097+
10371098
unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
10381099
let shared = data.load(Ordering::Acquire);
10391100
let kind = shared as usize & KIND_MASK;
@@ -1114,6 +1175,14 @@ unsafe impl BytesImpl for SharedImpl {
11141175
(AtomicPtr::new(this.shared.cast()), this.offset, this.len)
11151176
}
11161177

1178+
unsafe fn from_bytes_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
1179+
SharedImpl {
1180+
shared: (*data.get_mut()).cast(),
1181+
offset: ptr,
1182+
len,
1183+
}
1184+
}
1185+
11171186
unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
11181187
let shared = data.load(Ordering::Relaxed);
11191188
shallow_clone_arc(shared as _, ptr, len)

src/bytes_mut.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,14 @@ unsafe impl crate::BytesImpl for SharedImpl {
16831683
(AtomicPtr::new(this.shared.cast()), this.ptr, this.len)
16841684
}
16851685

1686+
unsafe fn from_bytes_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
1687+
SharedImpl {
1688+
shared: (*data.get_mut()).cast(),
1689+
ptr,
1690+
len,
1691+
}
1692+
}
1693+
16861694
unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
16871695
let shared = data.load(Ordering::Relaxed) as *mut Shared;
16881696
increment_shared(shared);

0 commit comments

Comments
 (0)