1
1
//! Runtime implementation of [`format!`].
2
2
//!
3
- //! See [`format()`] for details.
3
+ //! See [`format`](format()) and [`write`](write()) for details.
4
4
//!
5
5
//! # Features
6
6
//! By default only [`Display`] is supported, the rest of the
@@ -24,7 +24,7 @@ use std::error::Error as StdError;
24
24
use std:: fmt:: Pointer ;
25
25
#[ cfg( feature = "number" ) ]
26
26
use std:: fmt:: { Binary , LowerExp , LowerHex , Octal , UpperExp , UpperHex } ;
27
- use std:: fmt:: { Debug , Display , Error as FmtError } ;
27
+ use std:: fmt:: { Debug , Display , Error as FmtError , Write } ;
28
28
use std:: hash:: Hash ;
29
29
use std:: num:: ParseIntError ;
30
30
@@ -494,21 +494,23 @@ impl<'a> FormatArgument<'a> {
494
494
}
495
495
}
496
496
497
- /// Runtime version of [`format !`].
497
+ /// Runtime version of [`write !`].
498
498
///
499
- /// Takes a string and a context, containing [`Formattable `] values, returns a
500
- /// string .
499
+ /// Takes a mutable [`Write `] e.g `&mut String`, a format string and a context,
500
+ /// containing [`Formattable`] values .
501
501
///
502
502
/// ```
503
- /// use template::{format , Formattable};
503
+ /// use template::{write , Formattable};
504
504
///
505
- /// let formatted = format(
505
+ /// let mut buf = String::new();
506
+ /// write(
507
+ /// &mut buf,
506
508
/// "{value:+05}", // could be dynamic
507
509
/// &[("value", Formattable::display(&12))].into_iter().collect(),
508
510
/// )
509
511
/// .unwrap();
510
512
///
511
- /// assert_eq!(formatted , format!("{:+05}", 12));
513
+ /// assert_eq!(buf , format!("{:+05}", 12));
512
514
/// ```
513
515
///
514
516
/// # Errors
@@ -518,16 +520,17 @@ impl<'a> FormatArgument<'a> {
518
520
/// failed.
519
521
///
520
522
/// For more details have a look at [`Error`] and [`FormatArgumentError`].
521
- pub fn format < K : Borrow < str > + Eq + Hash > (
523
+ pub fn write < K : Borrow < str > + Eq + Hash > (
524
+ out : & mut impl Write ,
522
525
mut format : & str ,
523
526
context : & HashMap < K , Formattable > ,
524
- ) -> Result < String > {
527
+ ) -> Result {
525
528
let format = & mut format;
526
- let mut out = String :: with_capacity ( format. len ( ) ) ;
527
529
let idx = & mut 0 ;
528
530
while !format. is_empty ( ) {
529
531
if format. starts_with ( "{{" ) || format. starts_with ( "}}" ) {
530
- out. push_str ( & format[ ..1 ] ) ;
532
+ out. write_str ( & format[ ..1 ] )
533
+ . map_err ( |e| Error :: FmtError ( e, * idx) ) ?;
531
534
step ( 2 , format, idx) ;
532
535
continue ;
533
536
}
@@ -548,7 +551,7 @@ pub fn format<K: Borrow<str> + Eq + Hash>(
548
551
. get ( ident)
549
552
. ok_or ( Error :: MissingValue ( ident. to_string ( ) , start) ) ?;
550
553
format_value (
551
- & mut out, value, width, precision, alignment, sign, hash, zero, trait_, * idx,
554
+ out, value, width, precision, alignment, sign, hash, zero, trait_, * idx,
552
555
) ?;
553
556
ensure ! (
554
557
format. starts_with( '}' ) ,
@@ -561,8 +564,41 @@ pub fn format<K: Borrow<str> + Eq + Hash>(
561
564
. chars ( )
562
565
. next ( )
563
566
. expect ( "should contain a char if not empty" ) ;
564
- out. push ( next) ;
567
+ out. write_char ( next) . map_err ( |e| Error :: FmtError ( e , * idx ) ) ? ;
565
568
step ( next. len_utf8 ( ) , format, idx) ;
566
569
}
570
+ Ok ( ( ) )
571
+ }
572
+
573
+ /// Runtime version of [`format!`].
574
+ ///
575
+ /// Takes a string and a context, containing [`Formattable`] values, returns a
576
+ /// string.
577
+ ///
578
+ /// ```
579
+ /// use template::{format, Formattable};
580
+ ///
581
+ /// let formatted = format(
582
+ /// "{value:+05}", // could be dynamic
583
+ /// &[("value", Formattable::display(&12))].into_iter().collect(),
584
+ /// )
585
+ /// .unwrap();
586
+ ///
587
+ /// assert_eq!(formatted, format!("{:+05}", 12));
588
+ /// ```
589
+ ///
590
+ /// # Errors
591
+ ///
592
+ /// It will return an error if the specified format string has invalid syntax,
593
+ /// the type doesn't implement the expected trait, or the formatting it self
594
+ /// failed.
595
+ ///
596
+ /// For more details have a look at [`Error`] and [`FormatArgumentError`].
597
+ pub fn format < K : Borrow < str > + Eq + Hash > (
598
+ format : & str ,
599
+ context : & HashMap < K , Formattable > ,
600
+ ) -> Result < String > {
601
+ let mut out = String :: with_capacity ( format. len ( ) ) ;
602
+ write ( & mut out, format, context) ?;
567
603
Ok ( out)
568
604
}
0 commit comments