@@ -23,7 +23,13 @@ crate trait FixedSizeEncoding: Default {
23
23
// FIXME(eddyb) make these generic functions, or at least defaults here.
24
24
// (same problem as above, needs `[u8; Self::BYTE_LEN]`)
25
25
// For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used.
26
+
27
+ /// Read a `Self` value (encoded as `Self::BYTE_LEN` bytes),
28
+ /// from `&b[i * Self::BYTE_LEN..]`, returning `None` if `i`
29
+ /// is not in bounds, or `Some(Self::from_bytes(...))` otherwise.
26
30
fn maybe_read_from_bytes_at ( b : & [ u8 ] , i : usize ) -> Option < Self > ;
31
+ /// Write a `Self` value (encoded as `Self::BYTE_LEN` bytes),
32
+ /// at `&mut b[i * Self::BYTE_LEN..]`, using `Self::write_to_bytes`.
27
33
fn write_to_bytes_at ( self , b : & mut [ u8 ] , i : usize ) ;
28
34
}
29
35
@@ -112,8 +118,11 @@ impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
112
118
}
113
119
}
114
120
115
- /// Random-access table, similar to `Vec<Option<T>>`, but without requiring
116
- /// encoding or decoding all the values eagerly and in-order.
121
+ /// Random-access table (i.e. offeringconstant-time `get`/`set`), similar to
122
+ /// `Vec<Option<T>>`, but without requiring encoding or decoding all the values
123
+ /// eagerly and in-order.
124
+ /// A total of `(max_idx + 1) * <Option<T> as FixedSizeEncoding>::BYTE_LEN` bytes
125
+ /// are used for a table, where `max_idx` is the largest index passed to `set`.
117
126
// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
118
127
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
119
128
// (not sure if that is possible given that the `Vec` is being resized now)
@@ -135,10 +144,16 @@ impl<T> Default for Table<T> where Option<T>: FixedSizeEncoding {
135
144
136
145
impl < T > Table < T > where Option < T > : FixedSizeEncoding {
137
146
crate fn set ( & mut self , i : usize , value : T ) {
147
+ // FIXME(eddyb) investigate more compact encodings for sparse tables.
148
+ // On the PR @michaelwoerister mentioned:
149
+ // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
150
+ // > trick (i.e. divide things into buckets of 32 or 64 items and then
151
+ // > store bit-masks of which item in each bucket is actually serialized).
138
152
let needed = ( i + 1 ) * <Option < T > >:: BYTE_LEN ;
139
153
if self . bytes . len ( ) < needed {
140
154
self . bytes . resize ( needed, 0 ) ;
141
155
}
156
+
142
157
Some ( value) . write_to_bytes_at ( & mut self . bytes , i) ;
143
158
}
144
159
@@ -170,12 +185,13 @@ impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
170
185
) -> Option < T > {
171
186
debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
172
187
173
- let bytes = & metadata. raw_bytes ( ) [ self . position . get ( ) ..] [ ..self . meta ] ;
188
+ let start = self . position . get ( ) ;
189
+ let bytes = & metadata. raw_bytes ( ) [ start..start + self . meta ] ;
174
190
<Option < T > >:: maybe_read_from_bytes_at ( bytes, i) ?
175
191
}
176
192
}
177
193
178
- /// Per-definition table, similar to `Table` but keyed on `DefIndex`.
194
+ /// Like a `Table` but using `DefIndex` instead of `usize` as keys .
179
195
// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
180
196
// and by using `newtype_index!` to define `DefIndex`.
181
197
crate struct PerDefTable < T > ( Table < T > ) where Option < T > : FixedSizeEncoding ;
0 commit comments