21
21
//! playground: &None,
22
22
//! heading_offset: HeadingOffset::H2,
23
23
//! };
24
- //! let html = md.into_string();
24
+ //! let mut html = String::new();
25
+ //! md.write_into(&mut html).unwrap();
25
26
//! // ... something using html
26
27
//! ```
27
28
28
29
use std:: borrow:: Cow ;
29
30
use std:: collections:: VecDeque ;
30
- use std:: fmt:: Write ;
31
+ use std:: fmt:: { self , Write } ;
31
32
use std:: iter:: Peekable ;
32
33
use std:: ops:: { ControlFlow , Range } ;
33
34
use std:: path:: PathBuf ;
@@ -1327,17 +1328,32 @@ impl LangString {
1327
1328
}
1328
1329
}
1329
1330
1331
+ trait WriteSpec {
1332
+ fn reserve_spec ( & mut self , additional : usize ) ;
1333
+ }
1334
+
1335
+ impl < W : fmt:: Write > WriteSpec for W {
1336
+ #[ inline]
1337
+ default fn reserve_spec ( & mut self , _additional : usize ) { }
1338
+ }
1339
+
1340
+ impl < ' a > WriteSpec for & ' a mut String {
1341
+ #[ inline]
1342
+ fn reserve_spec ( & mut self , additional : usize ) {
1343
+ self . reserve ( additional) ;
1344
+ }
1345
+ }
1346
+
1330
1347
impl < ' a > Markdown < ' a > {
1331
- pub fn into_string ( self ) -> String {
1348
+ pub fn write_into ( self , mut f : impl fmt :: Write ) -> fmt :: Result {
1332
1349
// This is actually common enough to special-case
1333
1350
if self . content . is_empty ( ) {
1334
- return String :: new ( ) ;
1351
+ return Ok ( ( ) ) ;
1335
1352
}
1336
1353
1337
- let mut s = String :: with_capacity ( self . content . len ( ) * 3 / 2 ) ;
1338
- html:: push_html ( & mut s, self . into_iter ( ) ) ;
1354
+ f. reserve_spec ( self . content . len ( ) * 3 / 2 ) ;
1339
1355
1340
- s
1356
+ html :: write_html_fmt ( f , self . into_iter ( ) )
1341
1357
}
1342
1358
1343
1359
fn into_iter ( self ) -> CodeBlocks < ' a , ' a , impl Iterator < Item = Event < ' a > > > {
@@ -1453,19 +1469,20 @@ impl MarkdownWithToc<'_> {
1453
1469
1454
1470
( toc. into_toc ( ) , s)
1455
1471
}
1456
- pub ( crate ) fn into_string ( self ) -> String {
1472
+
1473
+ pub ( crate ) fn write_into ( self , mut f : impl fmt:: Write ) -> fmt:: Result {
1457
1474
let ( toc, s) = self . into_parts ( ) ;
1458
- format ! ( "<nav id=\" rustdoc\" >{toc}</nav>{s}" , toc = toc. print( ) )
1475
+ write ! ( f , "<nav id=\" rustdoc\" >{toc}</nav>{s}" , toc = toc. print( ) )
1459
1476
}
1460
1477
}
1461
1478
1462
1479
impl MarkdownItemInfo < ' _ > {
1463
- pub ( crate ) fn into_string ( self ) -> String {
1480
+ pub ( crate ) fn write_into ( self , mut f : impl fmt :: Write ) -> fmt :: Result {
1464
1481
let MarkdownItemInfo ( md, ids) = self ;
1465
1482
1466
1483
// This is actually common enough to special-case
1467
1484
if md. is_empty ( ) {
1468
- return String :: new ( ) ;
1485
+ return Ok ( ( ) ) ;
1469
1486
}
1470
1487
let p = Parser :: new_ext ( md, main_body_opts ( ) ) . into_offset_iter ( ) ;
1471
1488
@@ -1475,7 +1492,7 @@ impl MarkdownItemInfo<'_> {
1475
1492
_ => event,
1476
1493
} ) ;
1477
1494
1478
- let mut s = String :: with_capacity ( md. len ( ) * 3 / 2 ) ;
1495
+ f . reserve_spec ( md. len ( ) * 3 / 2 ) ;
1479
1496
1480
1497
ids. handle_footnotes ( |ids, existing_footnotes| {
1481
1498
let p = HeadingLinks :: new ( p, None , ids, HeadingOffset :: H1 ) ;
@@ -1484,10 +1501,8 @@ impl MarkdownItemInfo<'_> {
1484
1501
let p = p. filter ( |event| {
1485
1502
!matches ! ( event, Event :: Start ( Tag :: Paragraph ) | Event :: End ( TagEnd :: Paragraph ) )
1486
1503
} ) ;
1487
- html:: push_html ( & mut s, p) ;
1488
- } ) ;
1489
-
1490
- s
1504
+ html:: write_html_fmt ( & mut f, p)
1505
+ } )
1491
1506
}
1492
1507
}
1493
1508
0 commit comments