asciidork-parser 0.33.0

Asciidork parser
Documentation
use crate::internal::*;

pub struct CollectText<'arena> {
  bump: &'arena Bump,
  string: Option<BumpString<'arena>>,
  pub loc: SourceLocation,
}

impl<'arena> CollectText<'arena> {
  pub fn new_in(loc: SourceLocation, bump: &'arena bumpalo::Bump) -> Self {
    CollectText {
      bump,
      string: Some(BumpString::with_capacity_in(16, bump)),
      loc,
    }
  }

  pub fn push_token(&mut self, token: &Token<'_>) {
    self.string.as_mut().unwrap().push_str(&token.lexeme);
    self.loc.extend(token.loc);
  }

  pub fn push_str(&mut self, s: &str) {
    self.string.as_mut().unwrap().push_str(s);
    self.loc.end += s.len() as u32;
  }

  pub fn str(&self) -> &str {
    self.string.as_ref().unwrap()
  }

  pub fn trim_end(&mut self) {
    let string = self.string.as_mut().unwrap();
    if !string.ends_with(' ') {
      return;
    }
    let trimmed = string.trim_end();
    let mut delta = string.len() - trimmed.len();
    self.loc.end -= delta as u32;
    while delta > 0 {
      string.pop();
      delta -= 1;
    }
  }

  pub fn drop_last(&mut self, n: u32) {
    debug_assert!(n as usize <= self.string.as_ref().unwrap().len());
    let string = self.string.as_mut().unwrap();
    for _ in 0..n {
      string.pop();
    }
    self.loc.end -= n;
  }

  fn take(&mut self) -> BumpString<'arena> {
    self.loc = self.loc.clamp_end();
    self
      .string
      .replace(BumpString::with_capacity_in(16, self.bump))
      .unwrap()
  }

  pub fn take_src(&mut self) -> SourceString<'arena> {
    let src_loc = self.loc;
    SourceString::new(self.take(), src_loc)
  }

  pub fn drop_src(&mut self) {
    self.take();
  }

  pub fn commit_inlines(&mut self, inlines: &mut InlineNodes<'arena>) {
    match (self.is_empty(), inlines.last_mut()) {
      (false, Some(InlineNode { content: Inline::Text(text), loc })) => {
        text.push_str(&self.take());
        loc.extend(self.loc);
      }
      (false, _) => {
        inlines.push(InlineNode {
          loc: self.loc,
          content: Inline::Text(self.take()),
        });
        self.loc = self.loc.clamp_end();
      }
      _ => {}
    }
  }

  pub fn is_empty(&self) -> bool {
    self.string.as_ref().unwrap().len() == 0
  }

  pub fn ends_with(&self, predicate: impl FnMut(char) -> bool) -> bool {
    self.string.as_ref().unwrap().ends_with(predicate)
  }
}

impl std::fmt::Debug for CollectText<'_> {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    write!(
      f,
      "CollectText {{ string: {}, loc: {:?} }}",
      self
        .string
        .as_ref()
        .map_or("None".to_string(), |s| format!("Some({s:?})")),
      self.loc
    )
  }
}