@@ -6,6 +6,7 @@ use std::cmp::Ordering;
66use std:: collections:: Bound ;
77use std:: fmt:: { Debug , Formatter } ;
88use std:: hash:: { Hash , Hasher } ;
9+ use std:: marker:: PhantomData ;
910use std:: ops:: { Deref , RangeBounds } ;
1011
1112use bytes:: { Buf , Bytes } ;
@@ -20,7 +21,7 @@ pub struct Buffer<T> {
2021 pub ( crate ) bytes : Bytes ,
2122 pub ( crate ) length : usize ,
2223 pub ( crate ) alignment : Alignment ,
23- pub ( crate ) _marker : std :: marker :: PhantomData < T > ,
24+ pub ( crate ) _marker : PhantomData < T > ,
2425}
2526
2627impl < T > Clone for Buffer < T > {
@@ -30,7 +31,18 @@ impl<T> Clone for Buffer<T> {
3031 bytes : self . bytes . clone ( ) ,
3132 length : self . length ,
3233 alignment : self . alignment ,
33- _marker : std:: marker:: PhantomData ,
34+ _marker : PhantomData ,
35+ }
36+ }
37+ }
38+
39+ impl < T > Default for Buffer < T > {
40+ fn default ( ) -> Self {
41+ Self {
42+ bytes : Default :: default ( ) ,
43+ length : 0 ,
44+ alignment : Alignment :: of :: < T > ( ) ,
45+ _marker : PhantomData ,
3446 }
3547 }
3648}
@@ -42,6 +54,18 @@ impl<T> PartialEq for Buffer<T> {
4254 }
4355}
4456
57+ impl < T : PartialEq > PartialEq < Vec < T > > for Buffer < T > {
58+ fn eq ( & self , other : & Vec < T > ) -> bool {
59+ self . as_ref ( ) == other. as_slice ( )
60+ }
61+ }
62+
63+ impl < T : PartialEq > PartialEq < Buffer < T > > for Vec < T > {
64+ fn eq ( & self , other : & Buffer < T > ) -> bool {
65+ self . as_slice ( ) == other. as_ref ( )
66+ }
67+ }
68+
4569impl < T > Eq for Buffer < T > { }
4670
4771impl < T > Ord for Buffer < T > {
@@ -502,14 +526,39 @@ impl<T> FromIterator<T> for Buffer<T> {
502526 }
503527}
504528
505- /// Only for `Buffer<u8>` can we zero-copy from a `Vec<u8>` since we can use a 1-byte alignment.
506- impl From < Vec < u8 > > for ByteBuffer {
507- fn from ( value : Vec < u8 > ) -> Self {
508- Self :: from ( Bytes :: from ( value) )
529+ // Helper struct to allow us to zero-copy any vec into a buffer
530+ #[ repr( transparent) ]
531+ struct Wrapper < T > ( Vec < T > ) ;
532+
533+ impl < T > AsRef < [ u8 ] > for Wrapper < T > {
534+ fn as_ref ( & self ) -> & [ u8 ] {
535+ let data = self . 0 . as_ptr ( ) . cast :: < u8 > ( ) ;
536+ let len = self . 0 . len ( ) * size_of :: < T > ( ) ;
537+ unsafe { std:: slice:: from_raw_parts ( data, len) }
538+ }
539+ }
540+
541+ impl < T > From < Vec < T > > for Buffer < T >
542+ where
543+ T : Send + ' static ,
544+ {
545+ fn from ( value : Vec < T > ) -> Self {
546+ let original_len = value. len ( ) ;
547+ let wrapped_vec = Wrapper ( value) ;
548+
549+ let bytes = Bytes :: from_owner ( wrapped_vec) ;
550+
551+ assert_eq ! ( bytes. as_ptr( ) . align_offset( align_of:: <T >( ) ) , 0 ) ;
552+
553+ Self {
554+ bytes,
555+ length : original_len,
556+ alignment : Alignment :: of :: < T > ( ) ,
557+ _marker : PhantomData ,
558+ }
509559 }
510560}
511561
512- /// Only for `Buffer<u8>` can we zero-copy from a `Bytes` since we can use a 1-byte alignment.
513562impl From < Bytes > for ByteBuffer {
514563 fn from ( bytes : Bytes ) -> Self {
515564 let length = bytes. len ( ) ;
@@ -596,7 +645,7 @@ impl<T> From<BufferMut<T>> for Buffer<T> {
596645mod test {
597646 use bytes:: Buf ;
598647
599- use crate :: { Alignment , ByteBuffer , buffer} ;
648+ use crate :: { Alignment , Buffer , ByteBuffer , buffer} ;
600649
601650 #[ test]
602651 fn align ( ) {
@@ -644,4 +693,12 @@ mod test {
644693 assert_eq ! ( buf. as_slice( ) , b"world" ) ;
645694 assert_eq ! ( buf. chunk( ) , b"world" ) ;
646695 }
696+
697+ #[ test]
698+ fn from_vec ( ) {
699+ let vec = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
700+ let buff = Buffer :: from ( vec. clone ( ) ) ;
701+ assert ! ( buff. is_aligned( Alignment :: of:: <i32 >( ) ) ) ;
702+ assert_eq ! ( vec, buff) ;
703+ }
647704}
0 commit comments