1+ use core:: any:: TypeId ;
12use core:: iter:: FromIterator ;
23use core:: ops:: { Deref , RangeBounds } ;
34use 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
134138struct 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> {
891912impl 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 ( ) ) )
@@ -906,7 +928,15 @@ struct StaticImpl(&'static [u8]);
906928unsafe impl BytesImpl for StaticImpl {
907929 fn into_bytes_parts ( this : Self ) -> ( AtomicPtr < ( ) > , * const u8 , usize ) {
908930 let mut bytes = mem:: ManuallyDrop :: new ( Bytes :: from_static ( this. 0 ) ) ;
909- ( mem:: take ( & mut bytes. data ) , bytes. ptr , bytes. len )
931+ (
932+ mem:: replace ( & mut bytes. data , AtomicPtr :: default ( ) ) ,
933+ bytes. ptr ,
934+ bytes. len ,
935+ )
936+ }
937+
938+ unsafe fn from_bytes_parts ( _data : & mut AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Self {
939+ StaticImpl ( slice:: from_raw_parts ( ptr, len) )
910940 }
911941
912942 unsafe fn clone ( _: & AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Bytes {
@@ -932,7 +962,6 @@ struct PromotableOddImpl(Promotable);
932962
933963enum Promotable {
934964 Owned ( Box < [ u8 ] > ) ,
935- #[ allow( dead_code) ]
936965 Shared ( SharedImpl ) ,
937966}
938967
@@ -952,6 +981,12 @@ unsafe impl BytesImpl for PromotableEvenImpl {
952981 ( AtomicPtr :: new ( data. cast ( ) ) , ptr, len)
953982 }
954983
984+ unsafe fn from_bytes_parts ( data : & mut AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Self {
985+ PromotableEvenImpl ( promotable_from_bytes_parts ( data, ptr, len, |shared| {
986+ ptr_map ( shared. cast ( ) , |addr| addr & !KIND_MASK )
987+ } ) )
988+ }
989+
955990 unsafe fn clone ( data : & AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Bytes {
956991 let shared = data. load ( Ordering :: Acquire ) ;
957992 let kind = shared as usize & KIND_MASK ;
@@ -994,6 +1029,30 @@ unsafe impl BytesImpl for PromotableEvenImpl {
9941029 }
9951030}
9961031
1032+ unsafe fn promotable_from_bytes_parts (
1033+ data : & mut AtomicPtr < ( ) > ,
1034+ ptr : * const u8 ,
1035+ len : usize ,
1036+ f : fn ( * mut ( ) ) -> * mut u8 ,
1037+ ) -> Promotable {
1038+ let shared = data. with_mut ( |p| * p) ;
1039+ let kind = shared as usize & KIND_MASK ;
1040+
1041+ if kind == KIND_ARC {
1042+ Promotable :: Shared ( SharedImpl :: from_bytes_parts ( data, ptr, len) )
1043+ } else {
1044+ debug_assert_eq ! ( kind, KIND_VEC ) ;
1045+
1046+ let buf = f ( shared) ;
1047+
1048+ let cap = ( ptr as usize - buf as usize ) + len;
1049+
1050+ let vec = Vec :: from_raw_parts ( buf, cap, cap) ;
1051+
1052+ Promotable :: Owned ( vec. into_boxed_slice ( ) )
1053+ }
1054+ }
1055+
9971056unsafe fn promotable_into_vec (
9981057 data : & mut AtomicPtr < ( ) > ,
9991058 ptr : * const u8 ,
@@ -1034,6 +1093,12 @@ unsafe impl BytesImpl for PromotableOddImpl {
10341093 ( AtomicPtr :: new ( ptr. cast ( ) ) , ptr, len)
10351094 }
10361095
1096+ unsafe fn from_bytes_parts ( data : & mut AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Self {
1097+ PromotableOddImpl ( promotable_from_bytes_parts ( data, ptr, len, |shared| {
1098+ shared. cast ( )
1099+ } ) )
1100+ }
1101+
10371102 unsafe fn clone ( data : & AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Bytes {
10381103 let shared = data. load ( Ordering :: Acquire ) ;
10391104 let kind = shared as usize & KIND_MASK ;
@@ -1114,6 +1179,14 @@ unsafe impl BytesImpl for SharedImpl {
11141179 ( AtomicPtr :: new ( this. shared . cast ( ) ) , this. offset , this. len )
11151180 }
11161181
1182+ unsafe fn from_bytes_parts ( data : & mut AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Self {
1183+ SharedImpl {
1184+ shared : ( data. with_mut ( |p| * p) ) . cast ( ) ,
1185+ offset : ptr,
1186+ len,
1187+ }
1188+ }
1189+
11171190 unsafe fn clone ( data : & AtomicPtr < ( ) > , ptr : * const u8 , len : usize ) -> Bytes {
11181191 let shared = data. load ( Ordering :: Relaxed ) ;
11191192 shallow_clone_arc ( shared as _ , ptr, len)
0 commit comments