11use std:: ffi:: OsStr ;
2- use std:: fmt:: Write ;
32use std:: fs:: { self , File } ;
43use std:: io:: prelude:: * ;
54use std:: io:: { self , BufReader } ;
@@ -10,7 +9,8 @@ use std::sync::LazyLock as Lazy;
109use itertools:: Itertools ;
1110use rustc_data_structures:: flock;
1211use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
13- use serde:: Serialize ;
12+ use serde:: ser:: SerializeSeq ;
13+ use serde:: { Serialize , Serializer } ;
1414
1515use super :: { collect_paths_for_type, ensure_trailing_slash, Context , BASIC_KEYWORDS } ;
1616use crate :: clean:: Crate ;
@@ -284,25 +284,43 @@ pub(super) fn write_shared(
284284 cx. write_shared ( SharedResource :: Unversioned { name } , contents, & options. emit ) ?;
285285 }
286286
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 > ) > {
288302 let mut ret = Vec :: new ( ) ;
289303 let mut krates = Vec :: new ( ) ;
290304
291305 if path. exists ( ) {
292- let prefix = format ! ( r#"{}[ "{}"]"# , key , krate) ;
306+ let prefix = format ! ( " \ " {}\" " , krate) ;
293307 for line in BufReader :: new ( File :: open ( path) ?) . lines ( ) {
294308 let line = line?;
295- if !line. starts_with ( key ) {
309+ if !line. starts_with ( '"' ) {
296310 continue ;
297311 }
298312 if line. starts_with ( & prefix) {
299313 continue ;
300314 }
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+ }
302321 krates. push (
303- line[ key. len ( ) + 2 ..]
304- . split ( '"' )
305- . next ( )
322+ line. split ( '"' )
323+ . find ( |s| !s. is_empty ( ) )
306324 . map ( |s| s. to_owned ( ) )
307325 . unwrap_or_else ( String :: new) ,
308326 ) ;
@@ -311,6 +329,20 @@ pub(super) fn write_shared(
311329 Ok ( ( ret, krates) )
312330 }
313331
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 `"`*.
314346 fn collect_json ( path : & Path , krate : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
315347 let mut ret = Vec :: new ( ) ;
316348 let mut krates = Vec :: new ( ) ;
@@ -526,13 +558,27 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
526558 } ,
527559 } ;
528560
529- #[ derive( Serialize ) ]
530561 struct Implementor {
531562 text : String ,
532563 synthetic : bool ,
533564 types : Vec < String > ,
534565 }
535566
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+
536582 let implementors = imps
537583 . iter ( )
538584 . filter_map ( |imp| {
@@ -563,9 +609,9 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
563609 }
564610
565611 let implementors = format ! (
566- r#"implementors[ "{}"] = {}; "# ,
612+ r#""{}":{} "# ,
567613 krate. name( cx. tcx( ) ) ,
568- serde_json:: to_string( & implementors) . unwrap ( )
614+ serde_json:: to_string( & implementors) . expect ( "failed serde conversion" ) ,
569615 ) ;
570616
571617 let mut mydst = dst. clone ( ) ;
@@ -576,16 +622,15 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
576622 mydst. push ( & format ! ( "{}.{}.js" , remote_item_type, remote_path[ remote_path. len( ) - 1 ] ) ) ;
577623
578624 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) ;
580626 all_implementors. push ( implementors) ;
581627 // Sort the implementors by crate so the file will be generated
582628 // identically even with rustdoc running in parallel.
583629 all_implementors. sort ( ) ;
584630
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 };" ) ;
589634 v. push_str (
590635 "if (window.register_implementors) {\
591636 window.register_implementors(implementors);\
0 commit comments