css_parse/traits/
cursor_sink.rs

1use crate::{Cursor, SourceCursor, Token};
2use bumpalo::collections::Vec;
3
4/// This trait provides the generic `impl` that [ToCursors][crate::ToCursors] can use. This provides just enough API
5/// surface for nodes to put the cursors they represent into some buffer which can later be read, the details of which
6/// are elided.
7pub trait CursorSink {
8	fn append(&mut self, c: Cursor);
9}
10
11pub trait SourceCursorSink<'a> {
12	fn append(&mut self, c: SourceCursor<'a>);
13}
14
15const SEPARATOR: Cursor = Cursor::dummy(Token::SPACE);
16
17impl<'a> CursorSink for Vec<'a, Cursor> {
18	fn append(&mut self, c: Cursor) {
19		// If two adjacent cursors which could not be re-tokenized in the same way if they were written out adjacently occur
20		// then they should be separated by some token.
21		if let Some(last) = self.last()
22			&& last.token().needs_separator_for(c.into())
23		{
24			self.push(SEPARATOR);
25		}
26		self.push(c);
27	}
28}
29
30impl<'a> SourceCursorSink<'a> for Vec<'a, SourceCursor<'a>> {
31	fn append(&mut self, c: SourceCursor<'a>) {
32		// If two adjacent cursors which could not be re-tokenized in the same way if they were written out adjacently occur
33		// then they should be separated by some token.
34		if let Some(last) = self.last()
35			&& last.token().needs_separator_for(c.token())
36		{
37			self.push(SourceCursor::from(SEPARATOR, " "));
38		}
39		self.push(c)
40	}
41}
42
43#[cfg(test)]
44mod test {
45	use super::*;
46	use crate::{ComponentValues, EmptyAtomSet, Parser, ToCursors};
47	use bumpalo::Bump;
48	use css_lexer::Lexer;
49
50	#[test]
51	fn test_cursor_sink_for_vec() {
52		use std::fmt::Write;
53		let source_text = "black white";
54		let bump = Bump::default();
55		let mut stream = Vec::new_in(&bump);
56		let lexer = Lexer::new(&EmptyAtomSet::ATOMS, source_text);
57		let mut parser = Parser::new(&bump, source_text, lexer);
58		parser.parse_entirely::<ComponentValues>().output.unwrap().to_cursors(&mut stream);
59		let mut str = String::new();
60		for c in stream {
61			write!(&mut str, "{}", SourceCursor::from(c, c.str_slice(source_text))).unwrap();
62		}
63		assert_eq!(str, "black white");
64	}
65}