9
9
//! [features](#features).
10
10
//!
11
11
//! ```
12
+ //! # use std::collections::HashMap;
12
13
//! use interpolator::{format, Formattable};
13
14
//!
14
15
//! let formatted = format(
15
16
//! "{value:+05}", // could be dynamic
16
- //! &[("value", Formattable::display(&12))].into_iter().collect(),
17
+ //! &[("value", Formattable::display(&12))]
18
+ //! .into_iter()
19
+ //! .collect::<HashMap<_, _>>(),
17
20
//! )?;
18
21
//!
19
22
//! assert_eq!(formatted, format!("{:+05}", 12));
@@ -55,10 +58,10 @@ use interpolator::{format, Formattable};
55
58
// reference
56
59
let items = [&"hello", &"hi", &"hey"].map(Formattable::display);
57
60
let items = Formattable::iter(&items);
58
- let format_str = "Greetings: {items:i..-1(`{}`)(, )} and `{items:i-1}`";
61
+ let format_str = "Greetings: {items:i..-1(`{}{outside} `)(, )} and `{items:i-1}{outside }`";
59
62
assert_eq!(
60
- format(format_str, &hash!("items" => items))?,
61
- "Greetings: `hello`, `hi` and `hey`"
63
+ format(format_str, &hash!("items" => items, "outside" => Formattable::display(&'!') ))?,
64
+ "Greetings: `hello! `, `hi! ` and `hey! `"
62
65
);
63
66
# return Ok::<(), interpolator::Error>(())
64
67
```"#
@@ -112,11 +115,14 @@ type Result<T = (), E = Error> = std::result::Result<T, E>;
112
115
/// string.
113
116
///
114
117
/// ```
118
+ /// # use std::collections::HashMap;
115
119
/// use interpolator::{format, Formattable};
116
120
///
117
121
/// let formatted = format(
118
122
/// "{value:+05}", // could be dynamic
119
- /// &[("value", Formattable::display(&12))].into_iter().collect(),
123
+ /// &[("value", Formattable::display(&12))]
124
+ /// .into_iter()
125
+ /// .collect::<HashMap<_, _>>(),
120
126
/// )
121
127
/// .unwrap();
122
128
///
@@ -130,28 +136,64 @@ type Result<T = (), E = Error> = std::result::Result<T, E>;
130
136
/// failed.
131
137
///
132
138
/// For more details have a look at [`Error`] and [`ParseError`].
133
- pub fn format < K : Borrow < str > + Eq + Hash > (
134
- format : & str ,
135
- context : & HashMap < K , Formattable > ,
136
- ) -> Result < String > {
139
+ pub fn format ( format : & str , context : & impl Context ) -> Result < String > {
137
140
let mut out = String :: with_capacity ( format. len ( ) ) ;
138
141
write ( & mut out, format, context) ?;
139
142
Ok ( out)
140
143
}
141
144
145
+ /// Context for `format` and `write`
146
+ pub trait Context {
147
+ /// Returns the [`Formattable`] for the requested key
148
+ fn get ( & self , key : & str ) -> Option < Formattable > ;
149
+ }
150
+
151
+ impl < K : Borrow < str > + Eq + Hash > Context for HashMap < K , Formattable < ' _ > > {
152
+ fn get ( & self , key : & str ) -> Option < Formattable > {
153
+ HashMap :: get ( self , key) . copied ( )
154
+ }
155
+ }
156
+
157
+ #[ cfg( feature = "iter" ) ]
158
+ struct IterContext < ' a > {
159
+ outer : & ' a dyn Context ,
160
+ inner : Formattable < ' a > ,
161
+ }
162
+
163
+ #[ cfg( feature = "iter" ) ]
164
+ impl < ' a > IterContext < ' a > {
165
+ fn new ( outer : & ' a impl Context , inner : Formattable < ' a > ) -> Self {
166
+ Self { outer, inner }
167
+ }
168
+ }
169
+
170
+ #[ cfg( feature = "iter" ) ]
171
+ impl < ' a > Context for IterContext < ' a > {
172
+ fn get ( & self , key : & str ) -> Option < Formattable > {
173
+ if key. is_empty ( ) {
174
+ Some ( self . inner )
175
+ } else {
176
+ self . outer . get ( key)
177
+ }
178
+ }
179
+ }
180
+
142
181
/// Runtime version of [`write!`].
143
182
///
144
183
/// Takes a mutable [`Write`] e.g. `&mut String`, a format string and a context,
145
184
/// containing [`Formattable`] values.
146
185
///
147
186
/// ```
187
+ /// # use std::collections::HashMap;
148
188
/// use interpolator::{write, Formattable};
149
189
///
150
190
/// let mut buf = String::new();
151
191
/// write(
152
192
/// &mut buf,
153
193
/// "{value:+05}", // could be dynamic
154
- /// &[("value", Formattable::display(&12))].into_iter().collect(),
194
+ /// &[("value", Formattable::display(&12))]
195
+ /// .into_iter()
196
+ /// .collect::<HashMap<_, _>>(),
155
197
/// )
156
198
/// .unwrap();
157
199
///
@@ -165,11 +207,7 @@ pub fn format<K: Borrow<str> + Eq + Hash>(
165
207
/// failed.
166
208
///
167
209
/// For more details have a look at [`Error`] and [`ParseError`].
168
- pub fn write < ' a , K : Borrow < str > + Eq + Hash , F : Borrow < Formattable < ' a > > > (
169
- out : & mut impl Write ,
170
- mut format : & str ,
171
- context : & ' a HashMap < K , F > ,
172
- ) -> Result {
210
+ pub fn write ( out : & mut impl Write , mut format : & str , context : & impl Context ) -> Result {
173
211
let format = & mut format;
174
212
let idx = & mut 0 ;
175
213
while !format. is_empty ( ) {
@@ -206,6 +244,7 @@ pub fn write<'a, K: Borrow<str> + Eq + Hash, F: Borrow<Formattable<'a>>>(
206
244
zero,
207
245
trait_,
208
246
* idx,
247
+ context,
209
248
) ?;
210
249
ensure ! ( format. starts_with( '}' ) , ParseError :: Expected ( "}" , * idx) ) ;
211
250
step ( 1 , format, idx) ;
0 commit comments