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,6 @@ 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 ;
14
12
15
13
use super :: { collect_paths_for_type, ensure_trailing_slash, Context , BASIC_KEYWORDS } ;
16
14
use crate :: clean:: Crate ;
@@ -284,25 +282,43 @@ pub(super) fn write_shared(
284
282
cx. write_shared ( SharedResource :: Unversioned { name } , contents, & options. emit ) ?;
285
283
}
286
284
287
- fn collect ( path : & Path , krate : & str , key : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
285
+ /// Read a file and return all lines that match the `"{crate}":{data},` format,
286
+ /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
287
+ ///
288
+ /// This forms the payload of files that look like this:
289
+ ///
290
+ /// ```javascript
291
+ /// var data = {
292
+ /// "{crate1}":{data},
293
+ /// "{crate2}":{data}
294
+ /// };
295
+ /// use_data(data);
296
+ /// ```
297
+ ///
298
+ /// The file needs to be formatted so that *only crate data lines start with `"`*.
299
+ fn collect ( path : & Path , krate : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
288
300
let mut ret = Vec :: new ( ) ;
289
301
let mut krates = Vec :: new ( ) ;
290
302
291
303
if path. exists ( ) {
292
- let prefix = format ! ( r#"{}[ "{}"]"# , key , krate) ;
304
+ let prefix = format ! ( " \ " {}\" " , krate) ;
293
305
for line in BufReader :: new ( File :: open ( path) ?) . lines ( ) {
294
306
let line = line?;
295
- if !line. starts_with ( key ) {
307
+ if !line. starts_with ( '"' ) {
296
308
continue ;
297
309
}
298
310
if line. starts_with ( & prefix) {
299
311
continue ;
300
312
}
301
- ret. push ( line. to_string ( ) ) ;
313
+ if line. ends_with ( "," ) {
314
+ ret. push ( line[ ..line. len ( ) - 1 ] . to_string ( ) ) ;
315
+ } else {
316
+ // No comma (it's the case for the last added crate line)
317
+ ret. push ( line. to_string ( ) ) ;
318
+ }
302
319
krates. push (
303
- line[ key. len ( ) + 2 ..]
304
- . split ( '"' )
305
- . next ( )
320
+ line. split ( '"' )
321
+ . find ( |s| !s. is_empty ( ) )
306
322
. map ( |s| s. to_owned ( ) )
307
323
. unwrap_or_else ( String :: new) ,
308
324
) ;
@@ -311,6 +327,20 @@ pub(super) fn write_shared(
311
327
Ok ( ( ret, krates) )
312
328
}
313
329
330
+ /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
331
+ /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
332
+ ///
333
+ /// This forms the payload of files that look like this:
334
+ ///
335
+ /// ```javascript
336
+ /// var data = JSON.parse('{\
337
+ /// "{crate1}":{data},\
338
+ /// "{crate2}":{data}\
339
+ /// }');
340
+ /// use_data(data);
341
+ /// ```
342
+ ///
343
+ /// The file needs to be formatted so that *only crate data lines start with `"`*.
314
344
fn collect_json ( path : & Path , krate : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
315
345
let mut ret = Vec :: new ( ) ;
316
346
let mut krates = Vec :: new ( ) ;
@@ -526,13 +556,40 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
526
556
} ,
527
557
} ;
528
558
529
- #[ derive( Serialize ) ]
530
559
struct Implementor {
531
560
text : String ,
532
561
synthetic : bool ,
533
562
types : Vec < String > ,
534
563
}
535
564
565
+ impl Implementor {
566
+ fn to_js_string ( & self ) -> String {
567
+ fn single_quote_string ( s : & str ) -> String {
568
+ let mut result = String :: with_capacity ( s. len ( ) + 2 ) ;
569
+ result. push_str ( "'" ) ;
570
+ for c in s. chars ( ) {
571
+ if c == '"' {
572
+ result. push_str ( "\" " ) ;
573
+ } else {
574
+ result. extend ( c. escape_default ( ) ) ;
575
+ }
576
+ }
577
+ result. push_str ( "'" ) ;
578
+ result
579
+ }
580
+ let text_esc = single_quote_string ( & self . text ) ;
581
+ if self . synthetic {
582
+ let types = self . types . iter ( ) . map ( |type_| single_quote_string ( type_) ) . join ( "," ) ;
583
+ // use `1` to represent a synthetic, because it's fewer bytes than `true`
584
+ format ! ( "[{text_esc},1,[{types}]]" )
585
+ } else {
586
+ // The types list is only used for synthetic impls.
587
+ // If this changes, `main.js` and `write_shared.rs` both need changed.
588
+ format ! ( "[{text_esc}]" )
589
+ }
590
+ }
591
+ }
592
+
536
593
let implementors = imps
537
594
. iter ( )
538
595
. filter_map ( |imp| {
@@ -563,9 +620,9 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
563
620
}
564
621
565
622
let implementors = format ! (
566
- r#"implementors[ "{}"] = {}; "# ,
623
+ r#""{}":[{}] "# ,
567
624
krate. name( cx. tcx( ) ) ,
568
- serde_json :: to_string ( & implementors ) . unwrap ( )
625
+ implementors . iter ( ) . map ( Implementor :: to_js_string ) . join ( "," )
569
626
) ;
570
627
571
628
let mut mydst = dst. clone ( ) ;
@@ -576,16 +633,15 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
576
633
mydst. push ( & format ! ( "{}.{}.js" , remote_item_type, remote_path[ remote_path. len( ) - 1 ] ) ) ;
577
634
578
635
let ( mut all_implementors, _) =
579
- try_err ! ( collect( & mydst, krate. name( cx. tcx( ) ) . as_str( ) , "implementors" ) , & mydst) ;
636
+ try_err ! ( collect( & mydst, krate. name( cx. tcx( ) ) . as_str( ) ) , & mydst) ;
580
637
all_implementors. push ( implementors) ;
581
638
// Sort the implementors by crate so the file will be generated
582
639
// identically even with rustdoc running in parallel.
583
640
all_implementors. sort ( ) ;
584
641
585
- let mut v = String :: from ( "(function() {var implementors = {};\n " ) ;
586
- for implementor in & all_implementors {
587
- writeln ! ( v, "{}" , * implementor) . unwrap ( ) ;
588
- }
642
+ let mut v = String :: from ( "(function() {var implementors = {\n " ) ;
643
+ v. push_str ( & all_implementors. join ( ",\n " ) ) ;
644
+ v. push_str ( "\n };" ) ;
589
645
v. push_str (
590
646
"if (window.register_implementors) {\
591
647
window.register_implementors(implementors);\
0 commit comments