@@ -8,7 +8,10 @@ use std::num::NonZeroUsize;
8
8
use log:: debug;
9
9
10
10
/// 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 {
12
15
const BYTE_LEN : usize ;
13
16
14
17
// FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
@@ -38,7 +41,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults {
38
41
b. len( ) / BYTE_LEN ,
39
42
)
40
43
} ;
41
- Self :: from_bytes( & b[ i] )
44
+ FixedSizeEncoding :: from_bytes( & b[ i] )
42
45
}
43
46
fn write_to_bytes_at( self , b: & mut [ u8 ] , i: usize ) {
44
47
const BYTE_LEN : usize = $byte_len;
@@ -69,37 +72,69 @@ impl FixedSizeEncoding for u32 {
69
72
}
70
73
}
71
74
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
77
117
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
78
118
// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
79
119
// 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).
81
123
bytes : Vec < u8 > ,
82
124
_marker : PhantomData < T > ,
83
125
}
84
126
85
- impl < T : LazyMeta < Meta = ( ) > > Table < T > {
127
+ impl < T > Table < T > where Option < T > : FixedSizeEncoding {
86
128
crate fn new ( len : usize ) -> Self {
87
129
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 ] ,
89
132
_marker : PhantomData ,
90
133
}
91
134
}
92
135
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) ;
103
138
}
104
139
105
140
crate fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -112,42 +147,37 @@ impl<T: LazyMeta<Meta = ()>> Table<T> {
112
147
}
113
148
}
114
149
115
- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for Table < T > {
150
+ impl < T > LazyMeta for Table < T > where Option < T > : FixedSizeEncoding {
116
151
type Meta = usize ;
117
152
118
153
fn min_size ( len : usize ) -> usize {
119
154
len
120
155
}
121
156
}
122
157
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).
125
160
#[ 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 > {
127
162
debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
128
163
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)
134
165
}
135
166
}
136
167
137
-
138
168
/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
139
169
// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
140
170
// 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 ;
142
172
143
- impl < T : LazyMeta < Meta = ( ) > > PerDefTable < T > {
173
+ impl < T > PerDefTable < T > where Option < T > : FixedSizeEncoding {
144
174
crate fn new ( def_index_count : usize ) -> Self {
145
175
PerDefTable ( Table :: new ( def_index_count) )
146
176
}
147
177
148
- crate fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
178
+ crate fn set ( & mut self , def_id : DefId , value : T ) {
149
179
assert ! ( def_id. is_local( ) ) ;
150
- self . 0 . record ( def_id. index . index ( ) , entry ) ;
180
+ self . 0 . set ( def_id. index . index ( ) , value ) ;
151
181
}
152
182
153
183
crate fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -156,22 +186,22 @@ impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
156
186
}
157
187
}
158
188
159
- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for PerDefTable < T > {
189
+ impl < T > LazyMeta for PerDefTable < T > where Option < T > : FixedSizeEncoding {
160
190
type Meta = <Table < T > as LazyMeta >:: Meta ;
161
191
162
192
fn min_size ( meta : Self :: Meta ) -> usize {
163
193
Table :: < T > :: min_size ( meta)
164
194
}
165
195
}
166
196
167
- impl < T : Encodable > Lazy < PerDefTable < T > > {
197
+ impl < T > Lazy < PerDefTable < T > > where Option < T > : FixedSizeEncoding {
168
198
fn as_table ( & self ) -> Lazy < Table < T > > {
169
199
Lazy :: from_position_and_meta ( self . position , self . meta )
170
200
}
171
201
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).
173
203
#[ 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 ( ) )
176
206
}
177
207
}
0 commit comments