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 && last.needs_separator_for(c.token())
23 {
24 self.writer.write_char(' ')?;
25 }
26 self.last_token = Some(c.token());
27 self.writer.write_str(c.str_slice(source))?;
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, EmptyAtomSet, Parser, ToCursors};
48 use bumpalo::Bump;
49 use css_lexer::Lexer;
50
51 #[test]
52 fn test() {
53 let source_text = "foo{bar:baz();}";
54 let bump = Bump::default();
55 let mut str = String::new();
56 let mut stream = CursorWriteSink::new(source_text, &mut str);
57 let lexer = Lexer::new(&EmptyAtomSet::ATOMS, source_text);
58 let mut parser = Parser::new(&bump, source_text, lexer);
59 parser.parse_entirely::<ComponentValues>().output.unwrap().to_cursors(&mut stream);
60 assert_eq!(str, "foo{bar:baz();}");
61 }
62}