use crate::syntax::SyntaxKind;
use rowan::GreenNodeBuilder;
pub trait InlineSink {
fn token(&mut self, kind: rowan::SyntaxKind, text: &str);
fn start_node(&mut self, kind: rowan::SyntaxKind);
fn finish_node(&mut self);
}
impl InlineSink for GreenNodeBuilder<'_> {
#[inline]
fn token(&mut self, kind: rowan::SyntaxKind, text: &str) {
GreenNodeBuilder::token(self, kind, text);
}
#[inline]
fn start_node(&mut self, kind: rowan::SyntaxKind) {
GreenNodeBuilder::start_node(self, kind);
}
#[inline]
fn finish_node(&mut self) {
GreenNodeBuilder::finish_node(self);
}
}
pub(crate) struct MarkerInjectingSink<'a, 'b> {
inner: &'a mut GreenNodeBuilder<'static>,
marker_positions: &'b [(usize, usize, bool)],
idx: usize,
offset: usize,
}
impl<'a, 'b> MarkerInjectingSink<'a, 'b> {
pub(crate) fn new(
inner: &'a mut GreenNodeBuilder<'static>,
marker_positions: &'b [(usize, usize, bool)],
) -> Self {
Self {
inner,
marker_positions,
idx: 0,
offset: 0,
}
}
fn emit_markers_at_current(&mut self) {
while let Some(&(byte_offset, leading_spaces, has_trailing_space)) =
self.marker_positions.get(self.idx)
&& byte_offset == self.offset
{
if leading_spaces > 0 {
self.inner
.token(SyntaxKind::WHITESPACE.into(), &" ".repeat(leading_spaces));
}
self.inner.token(SyntaxKind::BLOCK_QUOTE_MARKER.into(), ">");
if has_trailing_space {
self.inner.token(SyntaxKind::WHITESPACE.into(), " ");
}
self.idx += 1;
}
}
pub(crate) fn finish(mut self) {
self.emit_markers_at_current();
}
}
impl InlineSink for MarkerInjectingSink<'_, '_> {
fn token(&mut self, kind: rowan::SyntaxKind, text: &str) {
let mut start = 0;
while start < text.len() {
self.emit_markers_at_current();
let remaining = text.len() - start;
let next_marker_offset = self
.marker_positions
.get(self.idx)
.map(|(byte_offset, _, _)| *byte_offset);
if let Some(next) = next_marker_offset
&& next > self.offset
&& next < self.offset + remaining
{
let split_len = next - self.offset;
let end = start + split_len;
if end > start {
self.inner.token(kind, &text[start..end]);
self.offset += split_len;
start = end;
continue;
}
}
self.inner.token(kind, &text[start..]);
self.offset += remaining;
break;
}
}
fn start_node(&mut self, kind: rowan::SyntaxKind) {
self.emit_markers_at_current();
self.inner.start_node(kind);
}
fn finish_node(&mut self) {
self.inner.finish_node();
}
}