css_parse/traits/
cursor_sink.rs1use crate::{Cursor, SourceCursor, Token};
2use bumpalo::collections::Vec;
3
4pub 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 let Some(last) = self.last() {
22 if last.token().needs_separator_for(c.into()) {
23 self.push(SEPARATOR);
24 }
25 }
26 self.push(c);
27 }
28}
29
30impl<'a> SourceCursorSink<'a> for &mut Vec<'a, SourceCursor<'a>> {
31 fn append(&mut self, c: SourceCursor<'a>) {
32 if let Some(last) = self.last() {
35 if last.token().needs_separator_for(c.token()) {
36 self.push(SourceCursor::from(SEPARATOR, " "));
37 }
38 }
39 self.push(c);
40 }
41}
42
43pub struct CursorToSourceCursorSink<'a, T: SourceCursorSink<'a>> {
44 source: &'a str,
45 sink: T,
46}
47
48impl<'a, T: SourceCursorSink<'a>> CursorToSourceCursorSink<'a, T> {
49 pub fn new(source: &'a str, sink: T) -> Self {
50 Self { source, sink }
51 }
52}
53
54impl<'a, T: SourceCursorSink<'a>> CursorSink for CursorToSourceCursorSink<'a, T> {
55 fn append(&mut self, c: Cursor) {
56 self.sink.append(SourceCursor::from(c, c.str_slice(self.source)))
57 }
58}
59
60impl<'a> SourceCursorSink<'a> for &mut String {
61 fn append(&mut self, c: SourceCursor<'a>) {
62 use std::fmt::Write;
63 let _ = write!(self, "{c}");
64 }
65}
66
67#[cfg(test)]
68mod test {
69 use super::*;
70 use crate::{ToCursors, parse};
71 use bumpalo::Bump;
72
73 #[test]
74 fn test_cursor_sink_for_vec() {
75 let source_text = "black white";
76 let bump = Bump::default();
77 let mut stream = Vec::new_in(&bump);
78 parse!(in bump &source_text).to_cursors(&mut stream);
79 let mut str = String::new();
80 for sc in stream {
81 sc.write_str(source_text, &mut str).unwrap();
82 }
83 assert_eq!(str, "black white");
84 }
85
86 #[test]
87 fn test_source_cursor_sink_for_string() {
88 let source_text = "black white";
89 let bump = Bump::default();
90 let mut str = String::new();
91 let mut transform = CursorToSourceCursorSink::new(source_text, &mut str);
92 parse!(in bump &source_text).to_cursors(&mut transform);
93 assert_eq!(str, "black white");
94 }
95}