@@ -7,13 +7,29 @@ use crate::Writer;
7
7
impl < W : AsyncWrite + Unpin > Writer < W > {
8
8
/// Writes the given event to the underlying writer. Async version of [`Writer::write_event`].
9
9
pub async fn write_event_async < ' a , E : AsRef < Event < ' a > > > ( & mut self , event : E ) -> Result < ( ) > {
10
- match * event. as_ref ( ) {
11
- Event :: Start ( ref e) => self . write_wrapped_async ( b"<" , e, b">" ) . await ,
12
- Event :: End ( ref e) => self . write_wrapped_async ( b"</" , e, b">" ) . await ,
10
+ let mut next_should_line_break = true ;
11
+ let result = match * event. as_ref ( ) {
12
+ Event :: Start ( ref e) => {
13
+ let result = self . write_wrapped_async ( b"<" , e, b">" ) . await ;
14
+ if let Some ( i) = self . indent . as_mut ( ) {
15
+ i. grow ( ) ;
16
+ }
17
+ result
18
+ }
19
+ Event :: End ( ref e) => {
20
+ if let Some ( i) = self . indent . as_mut ( ) {
21
+ i. shrink ( ) ;
22
+ }
23
+ self . write_wrapped_async ( b"</" , e, b">" ) . await
24
+ }
13
25
Event :: Empty ( ref e) => self . write_wrapped_async ( b"<" , e, b"/>" ) . await ,
14
- Event :: Text ( ref e) => self . write_async ( e) . await ,
26
+ Event :: Text ( ref e) => {
27
+ next_should_line_break = false ;
28
+ self . write_async ( e) . await
29
+ }
15
30
Event :: Comment ( ref e) => self . write_wrapped_async ( b"<!--" , e, b"-->" ) . await ,
16
31
Event :: CData ( ref e) => {
32
+ next_should_line_break = false ;
17
33
self . write_async ( b"<![CDATA[" ) . await ?;
18
34
self . write_async ( e) . await ?;
19
35
self . write_async ( b"]]>" ) . await
@@ -22,7 +38,23 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
22
38
Event :: PI ( ref e) => self . write_wrapped_async ( b"<?" , e, b"?>" ) . await ,
23
39
Event :: DocType ( ref e) => self . write_wrapped_async ( b"<!DOCTYPE " , e, b">" ) . await ,
24
40
Event :: Eof => Ok ( ( ) ) ,
41
+ } ;
42
+ if let Some ( i) = self . indent . as_mut ( ) {
43
+ i. should_line_break = next_should_line_break;
44
+ }
45
+ result
46
+ }
47
+
48
+ /// Manually write a newline and indentation at the proper level. Async version of
49
+ /// [`Writer::write_indent`].
50
+ ///
51
+ /// This method will do nothing if `Writer` was not constructed with [`Writer::new_with_indent`].
52
+ pub async fn write_indent_async ( & mut self ) -> Result < ( ) > {
53
+ if let Some ( ref i) = self . indent {
54
+ self . writer . write_all ( b"\n " ) . await ?;
55
+ self . writer . write_all ( i. current ( ) ) . await ?;
25
56
}
57
+ Ok ( ( ) )
26
58
}
27
59
28
60
#[ inline]
@@ -37,6 +69,12 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
37
69
value : & [ u8 ] ,
38
70
after : & [ u8 ] ,
39
71
) -> Result < ( ) > {
72
+ if let Some ( ref i) = self . indent {
73
+ if i. should_line_break {
74
+ self . writer . write_all ( b"\n " ) . await ?;
75
+ self . writer . write_all ( i. current ( ) ) . await ?;
76
+ }
77
+ }
40
78
self . write_async ( before) . await ?;
41
79
self . write_async ( value) . await ?;
42
80
self . write_async ( after) . await ?;
@@ -117,3 +155,188 @@ mod tests {
117
155
) ;
118
156
}
119
157
}
158
+
159
+ #[ cfg( test) ]
160
+ mod indentation_async {
161
+ use super :: * ;
162
+ use crate :: events:: * ;
163
+ use pretty_assertions:: assert_eq;
164
+
165
+ #[ tokio:: test]
166
+ async fn self_closed ( ) {
167
+ let mut buffer = Vec :: new ( ) ;
168
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
169
+
170
+ let tag = BytesStart :: new ( "self-closed" )
171
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
172
+ writer
173
+ . write_event_async ( Event :: Empty ( tag) )
174
+ . await
175
+ . expect ( "write tag failed" ) ;
176
+
177
+ assert_eq ! (
178
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
179
+ r#"<self-closed attr1="value1" attr2="value2"/>"#
180
+ ) ;
181
+ }
182
+
183
+ #[ tokio:: test]
184
+ async fn empty_paired ( ) {
185
+ let mut buffer = Vec :: new ( ) ;
186
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
187
+
188
+ let start = BytesStart :: new ( "paired" )
189
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
190
+ let end = start. to_end ( ) ;
191
+ writer
192
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
193
+ . await
194
+ . expect ( "write start tag failed" ) ;
195
+ writer
196
+ . write_event_async ( Event :: End ( end) )
197
+ . await
198
+ . expect ( "write end tag failed" ) ;
199
+
200
+ assert_eq ! (
201
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
202
+ r#"<paired attr1="value1" attr2="value2">
203
+ </paired>"#
204
+ ) ;
205
+ }
206
+
207
+ #[ tokio:: test]
208
+ async fn paired_with_inner ( ) {
209
+ let mut buffer = Vec :: new ( ) ;
210
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
211
+
212
+ let start = BytesStart :: new ( "paired" )
213
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
214
+ let end = start. to_end ( ) ;
215
+ let inner = BytesStart :: new ( "inner" ) ;
216
+
217
+ writer
218
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
219
+ . await
220
+ . expect ( "write start tag failed" ) ;
221
+ writer
222
+ . write_event_async ( Event :: Empty ( inner) )
223
+ . await
224
+ . expect ( "write inner tag failed" ) ;
225
+ writer
226
+ . write_event_async ( Event :: End ( end) )
227
+ . await
228
+ . expect ( "write end tag failed" ) ;
229
+
230
+ assert_eq ! (
231
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
232
+ r#"<paired attr1="value1" attr2="value2">
233
+ <inner/>
234
+ </paired>"#
235
+ ) ;
236
+ }
237
+
238
+ #[ tokio:: test]
239
+ async fn paired_with_text ( ) {
240
+ let mut buffer = Vec :: new ( ) ;
241
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
242
+
243
+ let start = BytesStart :: new ( "paired" )
244
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
245
+ let end = start. to_end ( ) ;
246
+ let text = BytesText :: new ( "text" ) ;
247
+
248
+ writer
249
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
250
+ . await
251
+ . expect ( "write start tag failed" ) ;
252
+ writer
253
+ . write_event_async ( Event :: Text ( text) )
254
+ . await
255
+ . expect ( "write text failed" ) ;
256
+ writer
257
+ . write_event_async ( Event :: End ( end) )
258
+ . await
259
+ . expect ( "write end tag failed" ) ;
260
+
261
+ assert_eq ! (
262
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
263
+ r#"<paired attr1="value1" attr2="value2">text</paired>"#
264
+ ) ;
265
+ }
266
+
267
+ #[ tokio:: test]
268
+ async fn mixed_content ( ) {
269
+ let mut buffer = Vec :: new ( ) ;
270
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
271
+
272
+ let start = BytesStart :: new ( "paired" )
273
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
274
+ let end = start. to_end ( ) ;
275
+ let text = BytesText :: new ( "text" ) ;
276
+ let inner = BytesStart :: new ( "inner" ) ;
277
+
278
+ writer
279
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
280
+ . await
281
+ . expect ( "write start tag failed" ) ;
282
+ writer
283
+ . write_event_async ( Event :: Text ( text) )
284
+ . await
285
+ . expect ( "write text failed" ) ;
286
+ writer
287
+ . write_event_async ( Event :: Empty ( inner) )
288
+ . await
289
+ . expect ( "write inner tag failed" ) ;
290
+ writer
291
+ . write_event_async ( Event :: End ( end) )
292
+ . await
293
+ . expect ( "write end tag failed" ) ;
294
+
295
+ assert_eq ! (
296
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
297
+ r#"<paired attr1="value1" attr2="value2">text<inner/>
298
+ </paired>"#
299
+ ) ;
300
+ }
301
+
302
+ #[ tokio:: test]
303
+ async fn nested ( ) {
304
+ let mut buffer = Vec :: new ( ) ;
305
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
306
+
307
+ let start = BytesStart :: new ( "paired" )
308
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
309
+ let end = start. to_end ( ) ;
310
+ let inner = BytesStart :: new ( "inner" ) ;
311
+
312
+ writer
313
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
314
+ . await
315
+ . expect ( "write start 1 tag failed" ) ;
316
+ writer
317
+ . write_event_async ( Event :: Start ( start. clone ( ) ) )
318
+ . await
319
+ . expect ( "write start 2 tag failed" ) ;
320
+ writer
321
+ . write_event_async ( Event :: Empty ( inner) )
322
+ . await
323
+ . expect ( "write inner tag failed" ) ;
324
+ writer
325
+ . write_event_async ( Event :: End ( end. clone ( ) ) )
326
+ . await
327
+ . expect ( "write end tag 2 failed" ) ;
328
+ writer
329
+ . write_event_async ( Event :: End ( end) )
330
+ . await
331
+ . expect ( "write end tag 1 failed" ) ;
332
+
333
+ assert_eq ! (
334
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
335
+ r#"<paired attr1="value1" attr2="value2">
336
+ <paired attr1="value1" attr2="value2">
337
+ <inner/>
338
+ </paired>
339
+ </paired>"#
340
+ ) ;
341
+ }
342
+ }
0 commit comments