@@ -8,7 +8,10 @@ use std::num::NonZeroUsize;
88use log:: debug;
99
1010/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
11- trait FixedSizeEncoding {
11+ /// Used mainly for Lazy positions and lengths.
12+ /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
13+ /// but this has no impact on safety.
14+ crate trait FixedSizeEncoding : Default {
1215 const BYTE_LEN : usize ;
1316
1417 // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
@@ -38,7 +41,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults {
3841 b. len( ) / BYTE_LEN ,
3942 )
4043 } ;
41- Self :: from_bytes( & b[ i] )
44+ FixedSizeEncoding :: from_bytes( & b[ i] )
4245 }
4346 fn write_to_bytes_at( self , b: & mut [ u8 ] , i: usize ) {
4447 const BYTE_LEN : usize = $byte_len;
@@ -69,37 +72,69 @@ impl FixedSizeEncoding for u32 {
6972 }
7073}
7174
72- /// Random-access position table, allowing encoding in an arbitrary order
73- /// (e.g. while visiting the definitions of a crate), and on-demand decoding
74- /// of specific indices (e.g. queries for per-definition data).
75- /// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
76- // FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
75+ // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
76+ // generic `Lazy<T>` impl, but in the general case we might not need / want to
77+ // fit every `usize` in `u32`.
78+ impl < T : Encodable > FixedSizeEncoding for Option < Lazy < T > > {
79+ fixed_size_encoding_byte_len_and_defaults ! ( u32 :: BYTE_LEN ) ;
80+
81+ fn from_bytes ( b : & [ u8 ] ) -> Self {
82+ Some ( Lazy :: from_position ( NonZeroUsize :: new ( u32:: from_bytes ( b) as usize ) ?) )
83+ }
84+
85+ fn write_to_bytes ( self , b : & mut [ u8 ] ) {
86+ let position = self . map_or ( 0 , |lazy| lazy. position . get ( ) ) ;
87+ let position: u32 = position. try_into ( ) . unwrap ( ) ;
88+
89+ position. write_to_bytes ( b)
90+ }
91+ }
92+
93+ impl < T : Encodable > FixedSizeEncoding for Option < Lazy < [ T ] > > {
94+ fixed_size_encoding_byte_len_and_defaults ! ( u32 :: BYTE_LEN * 2 ) ;
95+
96+ fn from_bytes ( b : & [ u8 ] ) -> Self {
97+ Some ( Lazy :: from_position_and_meta (
98+ <Option < Lazy < T > > >:: from_bytes ( b) ?. position ,
99+ u32:: from_bytes ( & b[ u32:: BYTE_LEN ..] ) as usize ,
100+ ) )
101+ }
102+
103+ fn write_to_bytes ( self , b : & mut [ u8 ] ) {
104+ self . map ( |lazy| Lazy :: < T > :: from_position ( lazy. position ) )
105+ . write_to_bytes ( b) ;
106+
107+ let len = self . map_or ( 0 , |lazy| lazy. meta ) ;
108+ let len: u32 = len. try_into ( ) . unwrap ( ) ;
109+
110+ len. write_to_bytes ( & mut b[ u32:: BYTE_LEN ..] ) ;
111+ }
112+ }
113+
114+ /// Random-access table, similar to `Vec<Option<T>>`, but without requiring
115+ /// encoding or decoding all the values eagerly and in-order.
116+ // FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
77117// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
78118// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
79119// and so would need two lengths in its metadata, which is not supported yet.
80- crate struct Table < T : LazyMeta < Meta = ( ) > > {
120+ crate struct Table < T > where Option < T > : FixedSizeEncoding {
121+ // FIXME(eddyb) store `[u8; <Option<T>>::BYTE_LEN]` instead of `u8` in `Vec`,
122+ // once that starts being allowed by the compiler (i.e. lazy normalization).
81123 bytes : Vec < u8 > ,
82124 _marker : PhantomData < T > ,
83125}
84126
85- impl < T : LazyMeta < Meta = ( ) > > Table < T > {
127+ impl < T > Table < T > where Option < T > : FixedSizeEncoding {
86128 crate fn new ( len : usize ) -> Self {
87129 Table {
88- bytes : vec ! [ 0 ; len * 4 ] ,
130+ // FIXME(eddyb) only allocate and encode as many entries as needed.
131+ bytes : vec ! [ 0 ; len * <Option <T >>:: BYTE_LEN ] ,
89132 _marker : PhantomData ,
90133 }
91134 }
92135
93- crate fn record ( & mut self , i : usize , entry : Lazy < T > ) {
94- let position: u32 = entry. position . get ( ) . try_into ( ) . unwrap ( ) ;
95-
96- assert ! ( u32 :: read_from_bytes_at( & self . bytes, i) == 0 ,
97- "recorded position for index {:?} twice, first at {:?} and now at {:?}" ,
98- i,
99- u32 :: read_from_bytes_at( & self . bytes, i) ,
100- position) ;
101-
102- position. write_to_bytes_at ( & mut self . bytes , i)
136+ crate fn set ( & mut self , i : usize , value : T ) {
137+ Some ( value) . write_to_bytes_at ( & mut self . bytes , i) ;
103138 }
104139
105140 crate fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -112,42 +147,37 @@ impl<T: LazyMeta<Meta = ()>> Table<T> {
112147 }
113148}
114149
115- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for Table < T > {
150+ impl < T > LazyMeta for Table < T > where Option < T > : FixedSizeEncoding {
116151 type Meta = usize ;
117152
118153 fn min_size ( len : usize ) -> usize {
119154 len
120155 }
121156}
122157
123- impl < T : Encodable > Lazy < Table < T > > {
124- /// Given the metadata, extract out the offset of a particular index (if any).
158+ impl < T > Lazy < Table < T > > where Option < T > : FixedSizeEncoding {
159+ /// Given the metadata, extract out the value at a particular index (if any).
125160 #[ inline( never) ]
126- crate fn lookup ( & self , bytes : & [ u8 ] , i : usize ) -> Option < Lazy < T > > {
161+ crate fn get ( & self , bytes : & [ u8 ] , i : usize ) -> Option < T > {
127162 debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
128163
129- let bytes = & bytes[ self . position . get ( ) ..] [ ..self . meta ] ;
130- let position = u32:: read_from_bytes_at ( bytes, i) ;
131- debug ! ( "Table::lookup: position={:?}" , position) ;
132-
133- NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
164+ <Option < T > >:: read_from_bytes_at ( & bytes[ self . position . get ( ) ..] [ ..self . meta ] , i)
134165 }
135166}
136167
137-
138168/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
139169// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
140170// and by using `newtype_index!` to define `DefIndex`.
141- crate struct PerDefTable < T : LazyMeta < Meta = ( ) > > ( Table < T > ) ;
171+ crate struct PerDefTable < T > ( Table < T > ) where Option < T > : FixedSizeEncoding ;
142172
143- impl < T : LazyMeta < Meta = ( ) > > PerDefTable < T > {
173+ impl < T > PerDefTable < T > where Option < T > : FixedSizeEncoding {
144174 crate fn new ( def_index_count : usize ) -> Self {
145175 PerDefTable ( Table :: new ( def_index_count) )
146176 }
147177
148- crate fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
178+ crate fn set ( & mut self , def_id : DefId , value : T ) {
149179 assert ! ( def_id. is_local( ) ) ;
150- self . 0 . record ( def_id. index . index ( ) , entry ) ;
180+ self . 0 . set ( def_id. index . index ( ) , value ) ;
151181 }
152182
153183 crate fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -156,22 +186,22 @@ impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
156186 }
157187}
158188
159- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for PerDefTable < T > {
189+ impl < T > LazyMeta for PerDefTable < T > where Option < T > : FixedSizeEncoding {
160190 type Meta = <Table < T > as LazyMeta >:: Meta ;
161191
162192 fn min_size ( meta : Self :: Meta ) -> usize {
163193 Table :: < T > :: min_size ( meta)
164194 }
165195}
166196
167- impl < T : Encodable > Lazy < PerDefTable < T > > {
197+ impl < T > Lazy < PerDefTable < T > > where Option < T > : FixedSizeEncoding {
168198 fn as_table ( & self ) -> Lazy < Table < T > > {
169199 Lazy :: from_position_and_meta ( self . position , self . meta )
170200 }
171201
172- /// Given the metadata, extract out the offset of a particular DefIndex (if any).
202+ /// Given the metadata, extract out the value at a particular DefIndex (if any).
173203 #[ inline( never) ]
174- crate fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
175- self . as_table ( ) . lookup ( bytes, def_index. index ( ) )
204+ crate fn get ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < T > {
205+ self . as_table ( ) . get ( bytes, def_index. index ( ) )
176206 }
177207}
0 commit comments