1
1
use std:: ffi:: OsStr ;
2
- use std:: fmt:: Write ;
3
2
use std:: fs:: { self , File } ;
4
3
use std:: io:: prelude:: * ;
5
4
use std:: io:: { self , BufReader } ;
@@ -10,7 +9,8 @@ use std::sync::LazyLock as Lazy;
10
9
use itertools:: Itertools ;
11
10
use rustc_data_structures:: flock;
12
11
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
13
- use serde:: Serialize ;
12
+ use serde:: ser:: SerializeSeq ;
13
+ use serde:: { Serialize , Serializer } ;
14
14
15
15
use super :: { collect_paths_for_type, ensure_trailing_slash, Context , BASIC_KEYWORDS } ;
16
16
use crate :: clean:: Crate ;
@@ -284,25 +284,43 @@ pub(super) fn write_shared(
284
284
cx. write_shared ( SharedResource :: Unversioned { name } , contents, & options. emit ) ?;
285
285
}
286
286
287
- fn collect ( path : & Path , krate : & str , key : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
287
+ /// Read a file and return all lines that match the `"{crate}":{data},` format,
288
+ /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
289
+ ///
290
+ /// This forms the payload of files that look like this:
291
+ ///
292
+ /// ```javascript
293
+ /// var data = {
294
+ /// "{crate1}":{data},
295
+ /// "{crate2}":{data}
296
+ /// };
297
+ /// use_data(data);
298
+ /// ```
299
+ ///
300
+ /// The file needs to be formatted so that *only crate data lines start with `"`*.
301
+ fn collect ( path : & Path , krate : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
288
302
let mut ret = Vec :: new ( ) ;
289
303
let mut krates = Vec :: new ( ) ;
290
304
291
305
if path. exists ( ) {
292
- let prefix = format ! ( r#"{}[ "{}"]"# , key , krate) ;
306
+ let prefix = format ! ( " \ " {}\" " , krate) ;
293
307
for line in BufReader :: new ( File :: open ( path) ?) . lines ( ) {
294
308
let line = line?;
295
- if !line. starts_with ( key ) {
309
+ if !line. starts_with ( '"' ) {
296
310
continue ;
297
311
}
298
312
if line. starts_with ( & prefix) {
299
313
continue ;
300
314
}
301
- ret. push ( line. to_string ( ) ) ;
315
+ if line. ends_with ( "," ) {
316
+ ret. push ( line[ ..line. len ( ) - 1 ] . to_string ( ) ) ;
317
+ } else {
318
+ // No comma (it's the case for the last added crate line)
319
+ ret. push ( line. to_string ( ) ) ;
320
+ }
302
321
krates. push (
303
- line[ key. len ( ) + 2 ..]
304
- . split ( '"' )
305
- . next ( )
322
+ line. split ( '"' )
323
+ . find ( |s| !s. is_empty ( ) )
306
324
. map ( |s| s. to_owned ( ) )
307
325
. unwrap_or_else ( String :: new) ,
308
326
) ;
@@ -311,6 +329,20 @@ pub(super) fn write_shared(
311
329
Ok ( ( ret, krates) )
312
330
}
313
331
332
+ /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
333
+ /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
334
+ ///
335
+ /// This forms the payload of files that look like this:
336
+ ///
337
+ /// ```javascript
338
+ /// var data = JSON.parse('{\
339
+ /// "{crate1}":{data},\
340
+ /// "{crate2}":{data}\
341
+ /// }');
342
+ /// use_data(data);
343
+ /// ```
344
+ ///
345
+ /// The file needs to be formatted so that *only crate data lines start with `"`*.
314
346
fn collect_json ( path : & Path , krate : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
315
347
let mut ret = Vec :: new ( ) ;
316
348
let mut krates = Vec :: new ( ) ;
@@ -526,13 +558,27 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
526
558
} ,
527
559
} ;
528
560
529
- #[ derive( Serialize ) ]
530
561
struct Implementor {
531
562
text : String ,
532
563
synthetic : bool ,
533
564
types : Vec < String > ,
534
565
}
535
566
567
+ impl Serialize for Implementor {
568
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
569
+ where
570
+ S : Serializer ,
571
+ {
572
+ let mut seq = serializer. serialize_seq ( None ) ?;
573
+ seq. serialize_element ( & self . text ) ?;
574
+ if self . synthetic {
575
+ seq. serialize_element ( & 1 ) ?;
576
+ seq. serialize_element ( & self . types ) ?;
577
+ }
578
+ seq. end ( )
579
+ }
580
+ }
581
+
536
582
let implementors = imps
537
583
. iter ( )
538
584
. filter_map ( |imp| {
@@ -563,9 +609,9 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
563
609
}
564
610
565
611
let implementors = format ! (
566
- r#"implementors[ "{}"] = {}; "# ,
612
+ r#""{}":{} "# ,
567
613
krate. name( cx. tcx( ) ) ,
568
- serde_json:: to_string( & implementors) . unwrap ( )
614
+ serde_json:: to_string( & implementors) . expect ( "failed serde conversion" ) ,
569
615
) ;
570
616
571
617
let mut mydst = dst. clone ( ) ;
@@ -576,16 +622,15 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
576
622
mydst. push ( & format ! ( "{}.{}.js" , remote_item_type, remote_path[ remote_path. len( ) - 1 ] ) ) ;
577
623
578
624
let ( mut all_implementors, _) =
579
- try_err ! ( collect( & mydst, krate. name( cx. tcx( ) ) . as_str( ) , "implementors" ) , & mydst) ;
625
+ try_err ! ( collect( & mydst, krate. name( cx. tcx( ) ) . as_str( ) ) , & mydst) ;
580
626
all_implementors. push ( implementors) ;
581
627
// Sort the implementors by crate so the file will be generated
582
628
// identically even with rustdoc running in parallel.
583
629
all_implementors. sort ( ) ;
584
630
585
- let mut v = String :: from ( "(function() {var implementors = {};\n " ) ;
586
- for implementor in & all_implementors {
587
- writeln ! ( v, "{}" , * implementor) . unwrap ( ) ;
588
- }
631
+ let mut v = String :: from ( "(function() {var implementors = {\n " ) ;
632
+ v. push_str ( & all_implementors. join ( ",\n " ) ) ;
633
+ v. push_str ( "\n };" ) ;
589
634
v. push_str (
590
635
"if (window.register_implementors) {\
591
636
window.register_implementors(implementors);\
0 commit comments