1
1
use std:: collections:: hash_map:: Entry ;
2
2
use std:: collections:: BTreeMap ;
3
3
4
- use rustc_data_structures:: fx:: FxHashMap ;
4
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
5
5
use rustc_middle:: ty:: TyCtxt ;
6
6
use rustc_span:: symbol:: Symbol ;
7
- use serde:: ser:: { Serialize , SerializeStruct , Serializer } ;
7
+ use serde:: ser:: { Serialize , SerializeSeq , SerializeStruct , Serializer } ;
8
8
9
9
use crate :: clean;
10
10
use crate :: clean:: types:: { Function , Generics , ItemId , Type , WherePredicate } ;
@@ -78,17 +78,17 @@ pub(crate) fn build_index<'tcx>(
78
78
map : & mut FxHashMap < F , usize > ,
79
79
itemid : F ,
80
80
lastpathid : & mut usize ,
81
- crate_paths : & mut Vec < ( ItemType , Symbol ) > ,
81
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
82
82
item_type : ItemType ,
83
- path : Symbol ,
83
+ path : & [ Symbol ] ,
84
84
) {
85
85
match map. entry ( itemid) {
86
86
Entry :: Occupied ( entry) => ty. id = Some ( RenderTypeId :: Index ( * entry. get ( ) ) ) ,
87
87
Entry :: Vacant ( entry) => {
88
88
let pathid = * lastpathid;
89
89
entry. insert ( pathid) ;
90
90
* lastpathid += 1 ;
91
- crate_paths. push ( ( item_type, path) ) ;
91
+ crate_paths. push ( ( item_type, path. to_vec ( ) ) ) ;
92
92
ty. id = Some ( RenderTypeId :: Index ( pathid) ) ;
93
93
}
94
94
}
@@ -100,7 +100,7 @@ pub(crate) fn build_index<'tcx>(
100
100
itemid_to_pathid : & mut FxHashMap < ItemId , usize > ,
101
101
primitives : & mut FxHashMap < Symbol , usize > ,
102
102
lastpathid : & mut usize ,
103
- crate_paths : & mut Vec < ( ItemType , Symbol ) > ,
103
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
104
104
) {
105
105
if let Some ( generics) = & mut ty. generics {
106
106
for item in generics {
@@ -131,7 +131,7 @@ pub(crate) fn build_index<'tcx>(
131
131
lastpathid,
132
132
crate_paths,
133
133
item_type,
134
- * fqp. last ( ) . unwrap ( ) ,
134
+ fqp,
135
135
) ;
136
136
} else {
137
137
ty. id = None ;
@@ -146,7 +146,7 @@ pub(crate) fn build_index<'tcx>(
146
146
lastpathid,
147
147
crate_paths,
148
148
ItemType :: Primitive ,
149
- sym,
149
+ & [ sym] ,
150
150
) ;
151
151
}
152
152
RenderTypeId :: Index ( _) => { }
@@ -191,7 +191,7 @@ pub(crate) fn build_index<'tcx>(
191
191
lastpathid += 1 ;
192
192
193
193
if let Some ( & ( ref fqp, short) ) = paths. get ( & defid) {
194
- crate_paths. push ( ( short, * fqp. last ( ) . unwrap ( ) ) ) ;
194
+ crate_paths. push ( ( short, fqp. clone ( ) ) ) ;
195
195
Some ( pathid)
196
196
} else {
197
197
None
@@ -213,118 +213,163 @@ pub(crate) fn build_index<'tcx>(
213
213
struct CrateData < ' a > {
214
214
doc : String ,
215
215
items : Vec < & ' a IndexItem > ,
216
- paths : Vec < ( ItemType , Symbol ) > ,
216
+ paths : Vec < ( ItemType , Vec < Symbol > ) > ,
217
217
// The String is alias name and the vec is the list of the elements with this alias.
218
218
//
219
219
// To be noted: the `usize` elements are indexes to `items`.
220
220
aliases : & ' a BTreeMap < String , Vec < usize > > ,
221
221
}
222
222
223
+ struct Paths {
224
+ ty : ItemType ,
225
+ name : Symbol ,
226
+ path : Option < usize > ,
227
+ }
228
+
229
+ impl Serialize for Paths {
230
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
231
+ where
232
+ S : Serializer ,
233
+ {
234
+ let mut seq = serializer. serialize_seq ( None ) ?;
235
+ seq. serialize_element ( & self . ty ) ?;
236
+ seq. serialize_element ( self . name . as_str ( ) ) ?;
237
+ if let Some ( ref path) = self . path {
238
+ seq. serialize_element ( path) ?;
239
+ }
240
+ seq. end ( )
241
+ }
242
+ }
243
+
223
244
impl < ' a > Serialize for CrateData < ' a > {
224
245
fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
225
246
where
226
247
S : Serializer ,
227
248
{
249
+ let mut extra_paths = FxHashMap :: default ( ) ;
250
+ // We need to keep the order of insertion, hence why we use an `IndexMap`. Then we will
251
+ // insert these "extra paths" (which are paths of items from external crates) into the
252
+ // `full_paths` list at the end.
253
+ let mut revert_extra_paths = FxIndexMap :: default ( ) ;
254
+ let mut mod_paths = FxHashMap :: default ( ) ;
255
+ for ( index, item) in self . items . iter ( ) . enumerate ( ) {
256
+ if item. path . is_empty ( ) {
257
+ continue ;
258
+ }
259
+ mod_paths. insert ( & item. path , index) ;
260
+ }
261
+ let mut paths = Vec :: with_capacity ( self . paths . len ( ) ) ;
262
+ for ( ty, path) in & self . paths {
263
+ if path. len ( ) < 2 {
264
+ paths. push ( Paths { ty : * ty, name : path[ 0 ] , path : None } ) ;
265
+ continue ;
266
+ }
267
+ let full_path = join_with_double_colon ( & path[ ..path. len ( ) - 1 ] ) ;
268
+ if let Some ( index) = mod_paths. get ( & full_path) {
269
+ paths. push ( Paths { ty : * ty, name : * path. last ( ) . unwrap ( ) , path : Some ( * index) } ) ;
270
+ continue ;
271
+ }
272
+ // It means it comes from an external crate so the item and its path will be
273
+ // stored into another array.
274
+ //
275
+ // `index` is put after the last `mod_paths`
276
+ let index = extra_paths. len ( ) + self . items . len ( ) ;
277
+ if !revert_extra_paths. contains_key ( & index) {
278
+ revert_extra_paths. insert ( index, full_path. clone ( ) ) ;
279
+ }
280
+ match extra_paths. entry ( full_path) {
281
+ Entry :: Occupied ( entry) => {
282
+ paths. push ( Paths {
283
+ ty : * ty,
284
+ name : * path. last ( ) . unwrap ( ) ,
285
+ path : Some ( * entry. get ( ) ) ,
286
+ } ) ;
287
+ }
288
+ Entry :: Vacant ( entry) => {
289
+ entry. insert ( index) ;
290
+ paths. push ( Paths {
291
+ ty : * ty,
292
+ name : * path. last ( ) . unwrap ( ) ,
293
+ path : Some ( index) ,
294
+ } ) ;
295
+ }
296
+ }
297
+ }
298
+
299
+ let mut names = Vec :: with_capacity ( self . items . len ( ) ) ;
300
+ let mut types = String :: with_capacity ( self . items . len ( ) ) ;
301
+ let mut full_paths = Vec :: with_capacity ( self . items . len ( ) ) ;
302
+ let mut descriptions = Vec :: with_capacity ( self . items . len ( ) ) ;
303
+ let mut parents = Vec :: with_capacity ( self . items . len ( ) ) ;
304
+ let mut functions = Vec :: with_capacity ( self . items . len ( ) ) ;
305
+ let mut deprecated = Vec :: with_capacity ( self . items . len ( ) ) ;
306
+
307
+ for ( index, item) in self . items . iter ( ) . enumerate ( ) {
308
+ let n = item. ty as u8 ;
309
+ let c = char:: try_from ( n + b'A' ) . expect ( "item types must fit in ASCII" ) ;
310
+ assert ! ( c <= 'z' , "item types must fit within ASCII printables" ) ;
311
+ types. push ( c) ;
312
+
313
+ assert_eq ! (
314
+ item. parent. is_some( ) ,
315
+ item. parent_idx. is_some( ) ,
316
+ "`{}` is missing idx" ,
317
+ item. name
318
+ ) ;
319
+ // 0 is a sentinel, everything else is one-indexed
320
+ parents. push ( item. parent_idx . map ( |x| x + 1 ) . unwrap_or ( 0 ) ) ;
321
+
322
+ names. push ( item. name . as_str ( ) ) ;
323
+ descriptions. push ( & item. desc ) ;
324
+
325
+ if !item. path . is_empty ( ) {
326
+ full_paths. push ( ( index, & item. path ) ) ;
327
+ }
328
+
329
+ // Fake option to get `0` out as a sentinel instead of `null`.
330
+ // We want to use `0` because it's three less bytes.
331
+ enum FunctionOption < ' a > {
332
+ Function ( & ' a IndexItemFunctionType ) ,
333
+ None ,
334
+ }
335
+ impl < ' a > Serialize for FunctionOption < ' a > {
336
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
337
+ where
338
+ S : Serializer ,
339
+ {
340
+ match self {
341
+ FunctionOption :: None => 0 . serialize ( serializer) ,
342
+ FunctionOption :: Function ( ty) => ty. serialize ( serializer) ,
343
+ }
344
+ }
345
+ }
346
+ functions. push ( match & item. search_type {
347
+ Some ( ty) => FunctionOption :: Function ( ty) ,
348
+ None => FunctionOption :: None ,
349
+ } ) ;
350
+
351
+ if item. deprecation . is_some ( ) {
352
+ deprecated. push ( index) ;
353
+ }
354
+ }
355
+
356
+ for ( index, path) in & revert_extra_paths {
357
+ full_paths. push ( ( * index, path) ) ;
358
+ }
359
+
228
360
let has_aliases = !self . aliases . is_empty ( ) ;
229
361
let mut crate_data =
230
362
serializer. serialize_struct ( "CrateData" , if has_aliases { 9 } else { 8 } ) ?;
231
363
crate_data. serialize_field ( "doc" , & self . doc ) ?;
232
- crate_data. serialize_field (
233
- "t" ,
234
- & self
235
- . items
236
- . iter ( )
237
- . map ( |item| {
238
- let n = item. ty as u8 ;
239
- let c = char:: try_from ( n + b'A' ) . expect ( "item types must fit in ASCII" ) ;
240
- assert ! ( c <= 'z' , "item types must fit within ASCII printables" ) ;
241
- c
242
- } )
243
- . collect :: < String > ( ) ,
244
- ) ?;
245
- crate_data. serialize_field (
246
- "n" ,
247
- & self . items . iter ( ) . map ( |item| item. name . as_str ( ) ) . collect :: < Vec < _ > > ( ) ,
248
- ) ?;
249
- crate_data. serialize_field (
250
- "q" ,
251
- & self
252
- . items
253
- . iter ( )
254
- . enumerate ( )
255
- // Serialize as an array of item indices and full paths
256
- . filter_map (
257
- |( index, item) | {
258
- if item. path . is_empty ( ) { None } else { Some ( ( index, & item. path ) ) }
259
- } ,
260
- )
261
- . collect :: < Vec < _ > > ( ) ,
262
- ) ?;
263
- crate_data. serialize_field (
264
- "d" ,
265
- & self . items . iter ( ) . map ( |item| & item. desc ) . collect :: < Vec < _ > > ( ) ,
266
- ) ?;
267
- crate_data. serialize_field (
268
- "i" ,
269
- & self
270
- . items
271
- . iter ( )
272
- . map ( |item| {
273
- assert_eq ! (
274
- item. parent. is_some( ) ,
275
- item. parent_idx. is_some( ) ,
276
- "`{}` is missing idx" ,
277
- item. name
278
- ) ;
279
- // 0 is a sentinel, everything else is one-indexed
280
- item. parent_idx . map ( |x| x + 1 ) . unwrap_or ( 0 )
281
- } )
282
- . collect :: < Vec < _ > > ( ) ,
283
- ) ?;
284
- crate_data. serialize_field (
285
- "f" ,
286
- & self
287
- . items
288
- . iter ( )
289
- . map ( |item| {
290
- // Fake option to get `0` out as a sentinel instead of `null`.
291
- // We want to use `0` because it's three less bytes.
292
- enum FunctionOption < ' a > {
293
- Function ( & ' a IndexItemFunctionType ) ,
294
- None ,
295
- }
296
- impl < ' a > Serialize for FunctionOption < ' a > {
297
- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
298
- where
299
- S : Serializer ,
300
- {
301
- match self {
302
- FunctionOption :: None => 0 . serialize ( serializer) ,
303
- FunctionOption :: Function ( ty) => ty. serialize ( serializer) ,
304
- }
305
- }
306
- }
307
- match & item. search_type {
308
- Some ( ty) => FunctionOption :: Function ( ty) ,
309
- None => FunctionOption :: None ,
310
- }
311
- } )
312
- . collect :: < Vec < _ > > ( ) ,
313
- ) ?;
314
- crate_data. serialize_field (
315
- "c" ,
316
- & self
317
- . items
318
- . iter ( )
319
- . enumerate ( )
320
- // Serialize as an array of deprecated item indices
321
- . filter_map ( |( index, item) | item. deprecation . map ( |_| index) )
322
- . collect :: < Vec < _ > > ( ) ,
323
- ) ?;
324
- crate_data. serialize_field (
325
- "p" ,
326
- & self . paths . iter ( ) . map ( |( it, s) | ( it, s. as_str ( ) ) ) . collect :: < Vec < _ > > ( ) ,
327
- ) ?;
364
+ crate_data. serialize_field ( "t" , & types) ?;
365
+ crate_data. serialize_field ( "n" , & names) ?;
366
+ // Serialize as an array of item indices and full paths
367
+ crate_data. serialize_field ( "q" , & full_paths) ?;
368
+ crate_data. serialize_field ( "d" , & descriptions) ?;
369
+ crate_data. serialize_field ( "i" , & parents) ?;
370
+ crate_data. serialize_field ( "f" , & functions) ?;
371
+ crate_data. serialize_field ( "c" , & deprecated) ?;
372
+ crate_data. serialize_field ( "p" , & paths) ?;
328
373
if has_aliases {
329
374
crate_data. serialize_field ( "a" , & self . aliases ) ?;
330
375
}
0 commit comments