1- use crate :: coder:: { Buffer , Decoder , Encoder , Result , View } ;
2- use crate :: { Decode , Encode } ;
3- use alloc:: vec:: Vec ;
4- use bytemuck:: CheckedBitPattern ;
5- use core:: num:: NonZeroUsize ;
1+ use super :: convert:: { impl_convert, ConvertFrom } ;
2+ use crate :: int:: ranged_int;
63use core:: time:: Duration ;
74
8- #[ derive( Default ) ]
9- pub struct DurationEncoder {
10- secs : <u64 as Encode >:: Encoder ,
11- subsec_nanos : <u32 as Encode >:: Encoder ,
12- }
13- impl Encoder < Duration > for DurationEncoder {
14- #[ inline( always) ]
15- fn encode ( & mut self , t : & Duration ) {
16- self . secs . encode ( & t. as_secs ( ) ) ;
17- self . subsec_nanos . encode ( & t. subsec_nanos ( ) ) ;
18- }
19- }
20- impl Buffer for DurationEncoder {
21- fn collect_into ( & mut self , out : & mut Vec < u8 > ) {
22- self . secs . collect_into ( out) ;
23- self . subsec_nanos . collect_into ( out) ;
24- }
5+ ranged_int ! ( Nanosecond , u32 , 0 , 999_999_999 ) ;
256
26- fn reserve ( & mut self , additional : NonZeroUsize ) {
27- self . secs . reserve ( additional) ;
28- self . subsec_nanos . reserve ( additional) ;
29- }
30- }
31- impl Encode for Duration {
32- type Encoder = DurationEncoder ;
33- }
7+ type DurationEncode = ( u64 , u32 ) ;
8+ type DurationDecode = ( u64 , Nanosecond ) ;
349
35- /// A u32 guaranteed to be < 1 billion. Prevents Duration::new from panicking.
36- #[ derive( Copy , Clone ) ]
37- #[ repr( transparent) ]
38- struct Nanoseconds ( u32 ) ;
39- // Safety: u32 and Nanoseconds have the same layout since Nanoseconds is #[repr(transparent)].
40- unsafe impl CheckedBitPattern for Nanoseconds {
41- type Bits = u32 ;
10+ impl ConvertFrom < & Duration > for DurationEncode {
4211 #[ inline( always) ]
43- fn is_valid_bit_pattern ( bits : & Self :: Bits ) -> bool {
44- * bits < 1_000_000_000
12+ fn convert_from ( value : & Duration ) -> Self {
13+ ( value . as_secs ( ) , value . subsec_nanos ( ) )
4514 }
4615}
47- impl < ' a > Decode < ' a > for Nanoseconds {
48- type Decoder = crate :: int:: CheckedIntDecoder < ' a , Nanoseconds , u32 > ;
49- }
5016
51- #[ derive( Default ) ]
52- pub struct DurationDecoder < ' a > {
53- secs : <u64 as Decode < ' a > >:: Decoder ,
54- subsec_nanos : <Nanoseconds as Decode < ' a > >:: Decoder ,
55- }
56- impl < ' a > View < ' a > for DurationDecoder < ' a > {
57- fn populate ( & mut self , input : & mut & ' a [ u8 ] , length : usize ) -> Result < ( ) > {
58- self . secs . populate ( input, length) ?;
59- self . subsec_nanos . populate ( input, length) ?;
60- Ok ( ( ) )
61- }
62- }
63- impl < ' a > Decoder < ' a , Duration > for DurationDecoder < ' a > {
17+ impl ConvertFrom < DurationDecode > for Duration {
6418 #[ inline( always) ]
65- fn decode ( & mut self ) -> Duration {
66- let secs = self . secs . decode ( ) ;
67- let Nanoseconds ( subsec_nanos) = self . subsec_nanos . decode ( ) ;
68- // Makes Duration::new 4x faster since it can skip checks and division.
69- // Safety: impl CheckedBitPattern for Nanoseconds guarantees this.
70- unsafe {
71- if !Nanoseconds :: is_valid_bit_pattern ( & subsec_nanos) {
72- core:: hint:: unreachable_unchecked ( ) ;
73- }
74- }
75- Duration :: new ( secs, subsec_nanos)
19+ fn convert_from ( value : DurationDecode ) -> Self {
20+ Duration :: new ( value. 0 , value. 1 . into_inner ( ) )
7621 }
7722}
78- impl < ' a > Decode < ' a > for Duration {
79- type Decoder = DurationDecoder < ' a > ;
80- }
23+
24+ impl_convert ! ( Duration , DurationEncode , DurationDecode ) ;
8125
8226#[ cfg( test) ]
8327mod tests {
@@ -95,5 +39,5 @@ mod tests {
9539 . map ( |( s, n) : ( _ , u32 ) | Duration :: new ( s, n % 1_000_000_000 ) )
9640 . collect ( )
9741 }
98- crate :: bench_encode_decode!( duration_vec: Vec <_ >) ;
42+ crate :: bench_encode_decode!( duration_vec: Vec <Duration >) ;
9943}
0 commit comments