css_parse/
cursor_write_sink.rs1use crate::{Cursor, CursorSink, SourceCursor, SourceCursorSink, Token};
2use core::fmt::{Result, Write};
3
4pub struct CursorWriteSink<'a, T: Write> {
8 source_text: &'a str,
9 writer: T,
10 last_token: Option<Token>,
11 err: Result,
12}
13
14impl<'a, T: Write> CursorWriteSink<'a, T> {
15 pub fn new(source_text: &'a str, writer: T) -> Self {
16 Self { source_text, writer, last_token: None, err: Ok(()) }
17 }
18
19 fn write(&mut self, c: Cursor, source: &'a str) -> Result {
20 self.err?;
21 if let Some(last) = self.last_token {
22 if last.needs_separator_for(c.token()) {
23 self.writer.write_char(' ')?;
24 }
25 }
26 self.last_token = Some(c.token());
27 c.write_str(source, &mut self.writer)?;
28 Ok(())
29 }
30}
31
32impl<'a, T: Write> CursorSink for CursorWriteSink<'a, T> {
33 fn append(&mut self, c: Cursor) {
34 self.err = self.write(c, self.source_text);
35 }
36}
37
38impl<'a, T: Write> SourceCursorSink<'a> for CursorWriteSink<'a, T> {
39 fn append(&mut self, c: SourceCursor<'a>) {
40 self.err = self.write(c.cursor(), c.source());
41 }
42}
43
44#[cfg(test)]
45mod test {
46 use super::*;
47 use crate::{ComponentValues, ToCursors, parse};
48 use bumpalo::Bump;
49
50 #[test]
51 fn test() {
52 let source_text = "foo{bar:baz();}";
53 let bump = Bump::default();
54 let mut str = String::new();
55 let mut stream = CursorWriteSink::new(source_text, &mut str);
56 parse!(in bump &source_text as ComponentValues).output.unwrap().to_cursors(&mut stream);
57 assert_eq!(str, "foo{bar:baz();}");
58 }
59}