90
90
use core:: borrow:: Borrow ;
91
91
use core:: hash:: { Hash , Hasher } ;
92
92
use core:: marker:: PhantomData ;
93
+ use core:: ops:: { Deref , DerefMut } ;
93
94
use core:: { cmp, fmt} ;
94
95
95
96
use alloc:: vec:: Vec ;
96
97
97
98
mod sealed {
98
- use super :: Features ;
99
-
100
- use alloc:: vec:: Vec ;
99
+ use super :: { FeatureFlags , Features } ;
101
100
102
101
/// The context in which [`Features`] are applicable. Defines which features are known to the
103
102
/// implementation, though specification of them as required or optional is up to the code
@@ -297,21 +296,21 @@ mod sealed {
297
296
298
297
/// Returns whether the feature is required by the given flags.
299
298
#[ inline]
300
- fn requires_feature( flags: & Vec < u8 > ) -> bool {
299
+ fn requires_feature( flags: & [ u8 ] ) -> bool {
301
300
flags. len( ) > Self :: BYTE_OFFSET &&
302
301
( flags[ Self :: BYTE_OFFSET ] & Self :: REQUIRED_MASK ) != 0
303
302
}
304
303
305
304
/// Returns whether the feature is supported by the given flags.
306
305
#[ inline]
307
- fn supports_feature( flags: & Vec < u8 > ) -> bool {
306
+ fn supports_feature( flags: & [ u8 ] ) -> bool {
308
307
flags. len( ) > Self :: BYTE_OFFSET &&
309
308
( flags[ Self :: BYTE_OFFSET ] & ( Self :: REQUIRED_MASK | Self :: OPTIONAL_MASK ) ) != 0
310
309
}
311
310
312
311
/// Sets the feature's required (even) bit in the given flags.
313
312
#[ inline]
314
- fn set_required_bit( flags: & mut Vec < u8 > ) {
313
+ fn set_required_bit( flags: & mut FeatureFlags ) {
315
314
if flags. len( ) <= Self :: BYTE_OFFSET {
316
315
flags. resize( Self :: BYTE_OFFSET + 1 , 0u8 ) ;
317
316
}
@@ -322,7 +321,7 @@ mod sealed {
322
321
323
322
/// Sets the feature's optional (odd) bit in the given flags.
324
323
#[ inline]
325
- fn set_optional_bit( flags: & mut Vec < u8 > ) {
324
+ fn set_optional_bit( flags: & mut FeatureFlags ) {
326
325
if flags. len( ) <= Self :: BYTE_OFFSET {
327
326
flags. resize( Self :: BYTE_OFFSET + 1 , 0u8 ) ;
328
327
}
@@ -333,7 +332,7 @@ mod sealed {
333
332
/// Clears the feature's required (even) and optional (odd) bits from the given
334
333
/// flags.
335
334
#[ inline]
336
- fn clear_bits( flags: & mut Vec < u8 > ) {
335
+ fn clear_bits( flags: & mut FeatureFlags ) {
337
336
if flags. len( ) > Self :: BYTE_OFFSET {
338
337
flags[ Self :: BYTE_OFFSET ] &= !Self :: REQUIRED_MASK ;
339
338
flags[ Self :: BYTE_OFFSET ] &= !Self :: OPTIONAL_MASK ;
@@ -661,6 +660,9 @@ mod sealed {
661
660
supports_trampoline_routing,
662
661
requires_trampoline_routing
663
662
) ;
663
+ // By default, allocate enough bytes to cover up to Trampoline. Update this as new features are
664
+ // added which we expect to appear commonly across contexts.
665
+ pub ( super ) const MIN_FEATURES_ALLOCATION_BYTES : usize = ( 57 + 7 ) / 8 ;
664
666
define_feature ! (
665
667
259 ,
666
668
DnsResolver ,
@@ -700,14 +702,131 @@ mod sealed {
700
702
const ANY_REQUIRED_FEATURES_MASK : u8 = 0b01_01_01_01 ;
701
703
const ANY_OPTIONAL_FEATURES_MASK : u8 = 0b10_10_10_10 ;
702
704
705
+ // Vecs are always 3 pointers long, so `FeatureFlags` is never shorter than 24 bytes on 64-bit
706
+ // platforms no matter what we do.
707
+ //
708
+ // Luckily, because `Vec` uses a `NonNull` pointer to its buffer, the two-variant enum is free
709
+ // space-wise, but we only get the remaining 2 usizes in length available for our own stuff (as any
710
+ // other value is interpreted as the `Heap` variant).
711
+ //
712
+ // Thus, as long as we never use more than 15 bytes for our Held variant `FeatureFlags` is the same
713
+ // length as a `Vec` in memory.
714
+ const DIRECT_ALLOC_BYTES : usize = if sealed:: MIN_FEATURES_ALLOCATION_BYTES > 8 * 2 - 1 {
715
+ sealed:: MIN_FEATURES_ALLOCATION_BYTES
716
+ } else {
717
+ 8 * 2 - 1
718
+ } ;
719
+ const _ASSERT: ( ) = assert ! ( DIRECT_ALLOC_BYTES <= u8 :: MAX as usize ) ;
720
+
721
+ /// The internal storage for feature flags. Public only for the [`sealed`] feature flag traits but
722
+ /// generally should never be used directly.
723
+ #[ derive( Clone , PartialEq , Eq ) ]
724
+ #[ doc( hidden) ]
725
+ pub enum FeatureFlags {
726
+ Held { bytes : [ u8 ; DIRECT_ALLOC_BYTES ] , len : u8 } ,
727
+ Heap ( Vec < u8 > ) ,
728
+ }
729
+
730
+ impl FeatureFlags {
731
+ fn empty ( ) -> Self {
732
+ Self :: Held { bytes : [ 0 ; DIRECT_ALLOC_BYTES ] , len : 0 }
733
+ }
734
+
735
+ fn from ( vec : Vec < u8 > ) -> Self {
736
+ if vec. len ( ) <= DIRECT_ALLOC_BYTES {
737
+ let mut bytes = [ 0 ; DIRECT_ALLOC_BYTES ] ;
738
+ bytes[ ..vec. len ( ) ] . copy_from_slice ( & vec) ;
739
+ Self :: Held { bytes, len : vec. len ( ) as u8 }
740
+ } else {
741
+ Self :: Heap ( vec)
742
+ }
743
+ }
744
+
745
+ fn resize ( & mut self , new_len : usize , default : u8 ) {
746
+ match self {
747
+ Self :: Held { bytes, len } => {
748
+ let start_len = * len as usize ;
749
+ if new_len <= DIRECT_ALLOC_BYTES {
750
+ bytes[ start_len..] . copy_from_slice ( & [ default; DIRECT_ALLOC_BYTES ] [ start_len..] ) ;
751
+ * len = new_len as u8 ;
752
+ } else {
753
+ let mut vec = Vec :: new ( ) ;
754
+ vec. resize ( new_len, default) ;
755
+ vec[ ..start_len] . copy_from_slice ( & bytes[ ..start_len] ) ;
756
+ * self = Self :: Heap ( vec) ;
757
+ }
758
+ } ,
759
+ Self :: Heap ( vec) => {
760
+ vec. resize ( new_len, default) ;
761
+ if new_len <= DIRECT_ALLOC_BYTES {
762
+ let mut bytes = [ 0 ; DIRECT_ALLOC_BYTES ] ;
763
+ bytes. copy_from_slice ( & vec[ ..new_len] ) ;
764
+ * self = Self :: Held { bytes, len : new_len as u8 } ;
765
+ }
766
+ } ,
767
+ }
768
+ }
769
+
770
+ fn len ( & self ) -> usize {
771
+ self . deref ( ) . len ( )
772
+ }
773
+
774
+ fn iter ( & self ) -> ( impl ExactSizeIterator < Item = & u8 > + DoubleEndedIterator < Item = & u8 > ) {
775
+ let slice = self . deref ( ) ;
776
+ slice. iter ( )
777
+ }
778
+
779
+ fn iter_mut (
780
+ & mut self ,
781
+ ) -> ( impl ExactSizeIterator < Item = & mut u8 > + DoubleEndedIterator < Item = & mut u8 > ) {
782
+ let slice = self . deref_mut ( ) ;
783
+ slice. iter_mut ( )
784
+ }
785
+ }
786
+
787
+ impl Deref for FeatureFlags {
788
+ type Target = [ u8 ] ;
789
+ fn deref ( & self ) -> & [ u8 ] {
790
+ match self {
791
+ FeatureFlags :: Held { bytes, len } => & bytes[ ..* len as usize ] ,
792
+ FeatureFlags :: Heap ( vec) => & vec,
793
+ }
794
+ }
795
+ }
796
+
797
+ impl DerefMut for FeatureFlags {
798
+ fn deref_mut ( & mut self ) -> & mut [ u8 ] {
799
+ match self {
800
+ FeatureFlags :: Held { bytes, len } => & mut bytes[ ..* len as usize ] ,
801
+ FeatureFlags :: Heap ( vec) => & mut vec[ ..] ,
802
+ }
803
+ }
804
+ }
805
+
806
+ impl PartialOrd for FeatureFlags {
807
+ fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
808
+ self . deref ( ) . partial_cmp ( other. deref ( ) )
809
+ }
810
+ }
811
+ impl Ord for FeatureFlags {
812
+ fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
813
+ self . deref ( ) . cmp ( other. deref ( ) )
814
+ }
815
+ }
816
+ impl fmt:: Debug for FeatureFlags {
817
+ fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
818
+ self . deref ( ) . fmt ( fmt)
819
+ }
820
+ }
821
+
703
822
/// Tracks the set of features which a node implements, templated by the context in which it
704
823
/// appears.
705
824
///
706
825
/// This is not exported to bindings users as we map the concrete feature types below directly instead
707
826
#[ derive( Eq ) ]
708
827
pub struct Features < T : sealed:: Context > {
709
828
/// Note that, for convenience, flags is LITTLE endian (despite being big-endian on the wire)
710
- flags : Vec < u8 > ,
829
+ flags : FeatureFlags ,
711
830
mark : PhantomData < T > ,
712
831
}
713
832
@@ -897,20 +1016,21 @@ impl ChannelTypeFeatures {
897
1016
impl < T : sealed:: Context > Features < T > {
898
1017
/// Create a blank Features with no features set
899
1018
pub fn empty ( ) -> Self {
900
- Features { flags : Vec :: new ( ) , mark : PhantomData }
1019
+ Features { flags : FeatureFlags :: empty ( ) , mark : PhantomData }
901
1020
}
902
1021
903
1022
/// Converts `Features<T>` to `Features<C>`. Only known `T` features relevant to context `C` are
904
1023
/// included in the result.
905
1024
fn to_context_internal < C : sealed:: Context > ( & self ) -> Features < C > {
906
1025
let from_byte_count = T :: KNOWN_FEATURE_MASK . len ( ) ;
907
1026
let to_byte_count = C :: KNOWN_FEATURE_MASK . len ( ) ;
908
- let mut flags = Vec :: new ( ) ;
1027
+ let mut flags = FeatureFlags :: empty ( ) ;
1028
+ flags. resize ( self . flags . len ( ) , 0 ) ;
909
1029
for ( i, byte) in self . flags . iter ( ) . enumerate ( ) {
910
1030
if i < from_byte_count && i < to_byte_count {
911
1031
let from_known_features = T :: KNOWN_FEATURE_MASK [ i] ;
912
1032
let to_known_features = C :: KNOWN_FEATURE_MASK [ i] ;
913
- flags. push ( byte & from_known_features & to_known_features) ;
1033
+ flags[ i ] = byte & from_known_features & to_known_features;
914
1034
}
915
1035
}
916
1036
Features :: < C > { flags, mark : PhantomData }
@@ -921,7 +1041,7 @@ impl<T: sealed::Context> Features<T> {
921
1041
///
922
1042
/// This is not exported to bindings users as we don't support export across multiple T
923
1043
pub fn from_le_bytes ( flags : Vec < u8 > ) -> Features < T > {
924
- Features { flags, mark : PhantomData }
1044
+ Features { flags : FeatureFlags :: from ( flags ) , mark : PhantomData }
925
1045
}
926
1046
927
1047
/// Returns the feature set as a list of bytes, in little-endian. This is in reverse byte order
@@ -936,7 +1056,7 @@ impl<T: sealed::Context> Features<T> {
936
1056
/// This is not exported to bindings users as we don't support export across multiple T
937
1057
pub fn from_be_bytes ( mut flags : Vec < u8 > ) -> Features < T > {
938
1058
flags. reverse ( ) ; // Swap to little-endian
939
- Self { flags, mark : PhantomData }
1059
+ Self { flags : FeatureFlags :: from ( flags ) , mark : PhantomData }
940
1060
}
941
1061
942
1062
/// Returns true if this `Features` has any optional flags set
0 commit comments