@@ -23,7 +23,13 @@ crate trait FixedSizeEncoding: Default {
2323 // FIXME(eddyb) make these generic functions, or at least defaults here.
2424 // (same problem as above, needs `[u8; Self::BYTE_LEN]`)
2525 // 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.
2630 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`.
2733 fn write_to_bytes_at ( self , b : & mut [ u8 ] , i : usize ) ;
2834}
2935
@@ -112,8 +118,11 @@ impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
112118 }
113119}
114120
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`.
117126// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
118127// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
119128// (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 {
135144
136145impl < T > Table < T > where Option < T > : FixedSizeEncoding {
137146 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).
138152 let needed = ( i + 1 ) * <Option < T > >:: BYTE_LEN ;
139153 if self . bytes . len ( ) < needed {
140154 self . bytes . resize ( needed, 0 ) ;
141155 }
156+
142157 Some ( value) . write_to_bytes_at ( & mut self . bytes , i) ;
143158 }
144159
@@ -170,12 +185,13 @@ impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
170185 ) -> Option < T > {
171186 debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
172187
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 ] ;
174190 <Option < T > >:: maybe_read_from_bytes_at ( bytes, i) ?
175191 }
176192}
177193
178- /// Per-definition table, similar to `Table` but keyed on `DefIndex`.
194+ /// Like a `Table` but using `DefIndex` instead of `usize` as keys .
179195// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
180196// and by using `newtype_index!` to define `DefIndex`.
181197crate struct PerDefTable < T > ( Table < T > ) where Option < T > : FixedSizeEncoding ;
0 commit comments