@@ -6,39 +6,98 @@ use std::marker::PhantomData;
66use std:: num:: NonZeroUsize ;
77use log:: debug;
88
9- /// Random-access position table, allowing encoding in an arbitrary order
10- /// (e.g. while visiting the definitions of a crate), and on-demand decoding
11- /// of specific indices (e.g. queries for per-definition data).
12- /// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
13- // FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
9+ /// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
10+ /// Used mainly for Lazy positions and lengths.
11+ /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
12+ /// but this has no impact on safety.
13+ pub trait FixedSizeEncoding : Default {
14+ const BYTE_LEN : usize ;
15+
16+ // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
17+ // once that starts being allowed by the compiler (i.e. lazy normalization).
18+ fn from_bytes ( b : & [ u8 ] ) -> Self ;
19+ fn write_to_bytes ( self , b : & mut [ u8 ] ) ;
20+ }
21+
22+ impl FixedSizeEncoding for u32 {
23+ const BYTE_LEN : usize = 4 ;
24+
25+ fn from_bytes ( b : & [ u8 ] ) -> Self {
26+ let mut bytes = [ 0 ; Self :: BYTE_LEN ] ;
27+ bytes. copy_from_slice ( & b[ ..Self :: BYTE_LEN ] ) ;
28+ Self :: from_le_bytes ( bytes)
29+ }
30+
31+ fn write_to_bytes ( self , b : & mut [ u8 ] ) {
32+ b[ ..Self :: BYTE_LEN ] . copy_from_slice ( & self . to_le_bytes ( ) ) ;
33+ }
34+ }
35+
36+ // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
37+ // generic `Lazy<T>` impl, but in the general case we might not need / want to
38+ // fit every `usize` in `u32`.
39+ impl < T : Encodable > FixedSizeEncoding for Option < Lazy < T > > {
40+ const BYTE_LEN : usize = u32:: BYTE_LEN ;
41+
42+ fn from_bytes ( b : & [ u8 ] ) -> Self {
43+ Some ( Lazy :: from_position ( NonZeroUsize :: new ( u32:: from_bytes ( b) as usize ) ?) )
44+ }
45+
46+ fn write_to_bytes ( self , b : & mut [ u8 ] ) {
47+ let position = self . map_or ( 0 , |lazy| lazy. position . get ( ) ) ;
48+ let position_u32 = position as u32 ;
49+ assert_eq ! ( position_u32 as usize , position) ;
50+
51+ position_u32. write_to_bytes ( b)
52+ }
53+ }
54+
55+ impl < T : Encodable > FixedSizeEncoding for Option < Lazy < [ T ] > > {
56+ const BYTE_LEN : usize = u32:: BYTE_LEN * 2 ;
57+
58+ fn from_bytes ( b : & [ u8 ] ) -> Self {
59+ Some ( Lazy :: from_position_and_meta (
60+ <Option < Lazy < T > > >:: from_bytes ( b) ?. position ,
61+ u32:: from_bytes ( & b[ u32:: BYTE_LEN ..] ) as usize ,
62+ ) )
63+ }
64+
65+ fn write_to_bytes ( self , b : & mut [ u8 ] ) {
66+ self . map ( |lazy| Lazy :: < T > :: from_position ( lazy. position ) )
67+ . write_to_bytes ( b) ;
68+
69+ let len = self . map_or ( 0 , |lazy| lazy. meta ) ;
70+ let len_u32 = len as u32 ;
71+ assert_eq ! ( len_u32 as usize , len) ;
72+
73+ len_u32. write_to_bytes ( & mut b[ u32:: BYTE_LEN ..] ) ;
74+ }
75+ }
76+
77+ /// Random-access table, similar to `Vec<Option<T>>`, but without requiring
78+ /// encoding or decoding all the values eagerly and in-order.
79+ // FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
1480// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
1581// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
1682// and so would need two lengths in its metadata, which is not supported yet.
17- pub struct Table < T : LazyMeta < Meta = ( ) > > {
83+ pub struct Table < T > where Option < T > : FixedSizeEncoding {
84+ // FIXME(eddyb) store `[u8; <Option<T>>::BYTE_LEN]` instead of `u8` in `Vec`,
85+ // once that starts being allowed by the compiler (i.e. lazy normalization).
1886 bytes : Vec < u8 > ,
1987 _marker : PhantomData < T > ,
2088}
2189
22- impl < T : LazyMeta < Meta = ( ) > > Table < T > {
90+ impl < T > Table < T > where Option < T > : FixedSizeEncoding {
2391 pub fn new ( len : usize ) -> Self {
2492 Table {
25- bytes : vec ! [ 0 ; len * 4 ] ,
93+ // FIXME(eddyb) only allocate and encode as many entries as needed.
94+ bytes : vec ! [ 0 ; len * <Option <T >>:: BYTE_LEN ] ,
2695 _marker : PhantomData ,
2796 }
2897 }
2998
30- pub fn record ( & mut self , i : usize , entry : Lazy < T > ) {
31- let position = entry. position . get ( ) as u32 ;
32- assert_eq ! ( position as usize , entry. position. get( ) ) ;
33-
34- let bytes = & mut self . bytes [ i * 4 ..] ;
35- assert ! ( read_le_u32( bytes) == 0 ,
36- "recorded position for index {:?} twice, first at {:?} and now at {:?}" ,
37- i,
38- read_le_u32( bytes) ,
39- position) ;
40-
41- write_le_u32 ( bytes, position) ;
99+ pub fn set ( & mut self , i : usize , value : T ) {
100+ Some ( value) . write_to_bytes ( & mut self . bytes [ i * <Option < T > >:: BYTE_LEN ..] ) ;
42101 }
43102
44103 pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -51,58 +110,45 @@ impl<T: LazyMeta<Meta = ()>> Table<T> {
51110 }
52111}
53112
54- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for Table < T > {
113+ impl < T > LazyMeta for Table < T > where Option < T > : FixedSizeEncoding {
55114 type Meta = usize ;
56115
57116 fn min_size ( len : usize ) -> usize {
58117 len
59118 }
60119}
61120
62- impl < T : Encodable > Lazy < Table < T > > {
63- /// Given the metadata, extract out the offset of a particular index (if any).
121+ impl < T > Lazy < Table < T > > where Option < T > : FixedSizeEncoding {
122+ /// Given the metadata, extract out the value at a particular index (if any).
64123 #[ inline( never) ]
65- pub fn lookup ( & self , bytes : & [ u8 ] , i : usize ) -> Option < Lazy < T > > {
124+ pub fn get ( & self , bytes : & [ u8 ] , i : usize ) -> Option < T > {
66125 debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
67126
68127 let bytes = & bytes[ self . position . get ( ) ..] [ ..self . meta ] ;
69- let position = read_le_u32 ( & bytes[ i * 4 ..] ) ;
70- debug ! ( "Table::lookup: position={:?}" , position) ;
71-
72- NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
128+ <Option < T > >:: from_bytes ( & bytes[ i * <Option < T > >:: BYTE_LEN ..] )
73129 }
74130}
75131
76- fn read_le_u32 ( b : & [ u8 ] ) -> u32 {
77- let mut bytes = [ 0 ; 4 ] ;
78- bytes. copy_from_slice ( & b[ ..4 ] ) ;
79- u32:: from_le_bytes ( bytes)
80- }
81-
82- fn write_le_u32 ( b : & mut [ u8 ] , x : u32 ) {
83- b[ ..4 ] . copy_from_slice ( & x. to_le_bytes ( ) ) ;
84- }
85-
86132/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
87133/// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in.
88- pub struct PerDefTable < T : LazyMeta < Meta = ( ) > > {
134+ pub struct PerDefTable < T > where Option < T > : FixedSizeEncoding {
89135 lo : Table < T > ,
90136 hi : Table < T > ,
91137}
92138
93- impl < T : LazyMeta < Meta = ( ) > > PerDefTable < T > {
139+ impl < T > PerDefTable < T > where Option < T > : FixedSizeEncoding {
94140 pub fn new ( ( max_index_lo, max_index_hi) : ( usize , usize ) ) -> Self {
95141 PerDefTable {
96142 lo : Table :: new ( max_index_lo) ,
97143 hi : Table :: new ( max_index_hi) ,
98144 }
99145 }
100146
101- pub fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
147+ pub fn set ( & mut self , def_id : DefId , value : T ) {
102148 assert ! ( def_id. is_local( ) ) ;
103149 let space_index = def_id. index . address_space ( ) . index ( ) ;
104150 let array_index = def_id. index . as_array_index ( ) ;
105- [ & mut self . lo , & mut self . hi ] [ space_index] . record ( array_index, entry ) ;
151+ [ & mut self . lo , & mut self . hi ] [ space_index] . set ( array_index, value ) ;
106152 }
107153
108154 pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
@@ -117,15 +163,15 @@ impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
117163 }
118164}
119165
120- impl < T : LazyMeta < Meta = ( ) > > LazyMeta for PerDefTable < T > {
166+ impl < T > LazyMeta for PerDefTable < T > where Option < T > : FixedSizeEncoding {
121167 type Meta = [ <Table < T > as LazyMeta >:: Meta ; 2 ] ;
122168
123169 fn min_size ( [ lo, hi] : Self :: Meta ) -> usize {
124170 Table :: < T > :: min_size ( lo) + Table :: < T > :: min_size ( hi)
125171 }
126172}
127173
128- impl < T : Encodable > Lazy < PerDefTable < T > > {
174+ impl < T > Lazy < PerDefTable < T > > where Option < T > : FixedSizeEncoding {
129175 fn table_for_space ( & self , space : DefIndexAddressSpace ) -> Lazy < Table < T > > {
130176 let space_index = space. index ( ) ;
131177 let offset = space_index. checked_sub ( 1 ) . map_or ( 0 , |i| self . meta [ i] ) ;
@@ -135,11 +181,10 @@ impl<T: Encodable> Lazy<PerDefTable<T>> {
135181 )
136182 }
137183
138- /// Given the metadata, extract out the offset of a particular DefIndex (if any).
184+ /// Given the metadata, extract out the value at a particular DefIndex (if any).
139185 #[ inline( never) ]
140- pub fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
186+ pub fn get ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < T > {
141187 self . table_for_space ( def_index. address_space ( ) )
142- . lookup ( bytes, def_index. as_array_index ( ) )
188+ . get ( bytes, def_index. as_array_index ( ) )
143189 }
144190}
145-
0 commit comments