extern crate alloc;
use alloc::{borrow::Cow, boxed::Box, format, string::String, vec, vec::Vec};
use core::{
any::Any,
error::Error as CoreError,
fmt::{self, Debug, Display, Formatter, Write},
iter::IntoIterator,
ops::{Index, IndexMut},
result::Result as CoreResult,
};
use bitflags::bitflags;
use crate::{
error::*,
text,
util::{StringMap, TinyVec},
};
#[derive(Default, Debug, Clone, Copy)]
pub struct NodeRef {
cell: usize,
id: usize,
}
impl NodeRef {
pub const fn new(cell: usize, id: usize) -> Self {
Self { cell, id }
}
}
impl PartialEq for NodeRef {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for NodeRef {}
pub const NODE_REF_UNDEFINED: NodeRef = NodeRef {
cell: usize::MAX,
id: usize::MAX,
};
impl Display for NodeRef {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "NodeRef(cell:{}, id:{})", self.cell, self.id)
}
}
impl NodeRef {
pub(crate) fn append_child_fast(self, arena: &mut Arena, child_ref: NodeRef) {
let lastref_opt = arena[self].last_child;
{
let s = &mut arena[self];
s.last_child = Some(child_ref);
if lastref_opt.is_none() {
s.first_child = Some(child_ref);
}
}
{
let child = &mut arena[child_ref];
child.parent = Some(self);
child.previous_sibling = lastref_opt;
}
if let Some(lastref) = lastref_opt {
arena[lastref].next_sibling = Some(child_ref);
} else {
arena[self].first_child = Some(child_ref);
}
}
#[inline(always)]
pub fn append_child(self, arena: &mut Arena, child_ref: NodeRef) {
self.try_append_child(arena, child_ref).unwrap();
}
pub fn try_append_child(self, arena: &mut Arena, child_ref: NodeRef) -> Result<()> {
if arena[child_ref].parent().is_some() {
child_ref.try_remove(arena)?;
}
let lastref_opt = arena.try_get(self)?.last_child;
arena[self].last_child = Some(child_ref);
if lastref_opt.is_none() {
arena[self].first_child = Some(child_ref);
}
{
let child = arena.try_get_mut(child_ref)?;
child.parent = Some(self);
child.previous_sibling = lastref_opt;
}
if let Some(lastref) = lastref_opt {
arena.try_get_mut(lastref)?.next_sibling = Some(child_ref);
} else {
arena[self].first_child = Some(child_ref);
}
Ok(())
}
#[inline(always)]
pub fn replace_child(self, arena: &mut Arena, target_ref: NodeRef, replacer_ref: NodeRef) {
self.try_replace_child(arena, target_ref, replacer_ref)
.unwrap();
}
pub fn try_replace_child(
self,
arena: &mut Arena,
target_ref: NodeRef,
replacer_ref: NodeRef,
) -> Result<()> {
if arena.try_get(target_ref)?.parent != Some(self) {
return Err(Error::invalid_node_operation(format!(
"Target node {:?} is not a child of node {:?}",
target_ref, self
)));
}
let previous_ref_opt = arena[target_ref].previous_sibling;
let next_ref_opt = arena[target_ref].next_sibling;
{
let replacer = arena.try_get_mut(replacer_ref)?;
replacer.parent = Some(self);
replacer.previous_sibling = previous_ref_opt;
replacer.next_sibling = next_ref_opt;
}
if let Some(prev_ref) = previous_ref_opt {
arena.try_get_mut(prev_ref)?.next_sibling = Some(replacer_ref);
} else {
arena.try_get_mut(self)?.first_child = Some(replacer_ref);
}
if let Some(next_ref) = next_ref_opt {
arena.try_get_mut(next_ref)?.previous_sibling = Some(replacer_ref);
} else {
arena.try_get_mut(self)?.last_child = Some(replacer_ref);
}
arena.arena[target_ref.cell] = None;
arena.free_indicies.push(target_ref.cell);
Ok(())
}
#[inline(always)]
pub fn insert_before(self, arena: &mut Arena, target_ref: NodeRef, insertee_ref: NodeRef) {
self.try_insert_before(arena, target_ref, insertee_ref)
.unwrap();
}
pub fn try_insert_before(
self,
arena: &mut Arena,
target_ref: NodeRef,
insertee_ref: NodeRef,
) -> Result<()> {
if arena[insertee_ref].parent().is_some() {
insertee_ref.try_remove(arena)?;
}
if arena.try_get(target_ref)?.parent != Some(self) {
return Err(Error::invalid_node_operation(format!(
"Target node {:?} is not a child of node {:?}",
target_ref, self
)));
}
let prev = arena[target_ref].previous_sibling;
{
let insertee = arena.try_get_mut(insertee_ref)?;
insertee.parent = Some(self);
insertee.next_sibling = Some(target_ref);
insertee.previous_sibling = prev;
}
if let Some(prev_ref) = arena[target_ref].previous_sibling {
arena.try_get_mut(prev_ref)?.next_sibling = Some(insertee_ref);
} else {
arena.try_get_mut(self)?.first_child = Some(insertee_ref);
}
arena[target_ref].previous_sibling = Some(insertee_ref);
if let Some(fc_ref) = arena.try_get(self)?.first_child {
if fc_ref == target_ref {
arena.try_get_mut(self)?.first_child = Some(insertee_ref);
}
}
Ok(())
}
#[inline(always)]
pub fn insert_after(self, arena: &mut Arena, target_ref: NodeRef, insertee_ref: NodeRef) {
self.try_insert_after(arena, target_ref, insertee_ref)
.unwrap();
}
pub fn try_insert_after(
self,
arena: &mut Arena,
target_ref: NodeRef,
insertee_ref: NodeRef,
) -> Result<()> {
if arena[insertee_ref].parent().is_some() {
insertee_ref.try_remove(arena)?;
}
if arena.try_get(target_ref)?.parent != Some(self) {
return Err(Error::invalid_node_operation(format!(
"Target node {:?} is not a child of node {:?}",
target_ref, self
)));
}
let next = arena[target_ref].next_sibling;
{
let insertee = arena.try_get_mut(insertee_ref)?;
insertee.parent = Some(self);
insertee.previous_sibling = Some(target_ref);
insertee.next_sibling = next;
}
if let Some(next_ref) = arena[target_ref].next_sibling {
arena.try_get_mut(next_ref)?.previous_sibling = Some(insertee_ref);
} else {
arena.try_get_mut(self)?.last_child = Some(insertee_ref);
}
arena[target_ref].next_sibling = Some(insertee_ref);
if let Some(lc_ref) = arena.try_get(self)?.last_child {
if lc_ref == target_ref {
arena.try_get_mut(self)?.last_child = Some(insertee_ref);
}
}
Ok(())
}
#[inline(always)]
pub fn remove(self, arena: &mut Arena) {
self.try_remove(arena).unwrap();
}
pub fn try_remove(self, arena: &mut Arena) -> Result<()> {
let parent_ref_opt;
let previous_ref_opt;
let next_ref_opt;
{
let node = arena.try_get(self)?;
parent_ref_opt = node.parent;
previous_ref_opt = node.previous_sibling;
next_ref_opt = node.next_sibling;
}
if let Some(parent_ref) = parent_ref_opt {
let mparent = arena.try_get_mut(parent_ref)?;
if mparent.first_child == Some(self) {
mparent.first_child = next_ref_opt;
}
if mparent.last_child == Some(self) {
mparent.last_child = previous_ref_opt;
}
}
if let Some(previous_ref) = previous_ref_opt {
let mprevious = arena.try_get_mut(previous_ref)?;
mprevious.next_sibling = next_ref_opt;
}
if let Some(next_ref) = next_ref_opt {
let mnext = arena.try_get_mut(next_ref)?;
mnext.previous_sibling = previous_ref_opt;
}
let node = arena.try_get_mut(self)?;
node.parent = None;
node.previous_sibling = None;
node.next_sibling = None;
Ok(())
}
#[inline(always)]
pub fn delete(self, arena: &mut Arena) {
self.try_delete(arena).unwrap();
}
pub fn try_delete(self, arena: &mut Arena) -> Result<()> {
let parent_ref_opt;
let previous_ref_opt;
let next_ref_opt;
let first_ref_opt;
{
let node = arena.try_get(self)?;
parent_ref_opt = node.parent;
previous_ref_opt = node.previous_sibling;
next_ref_opt = node.next_sibling;
first_ref_opt = node.first_child;
}
if let Some(parent_ref) = parent_ref_opt {
let mparent = arena.try_get_mut(parent_ref)?;
if mparent.first_child == Some(self) {
mparent.first_child = next_ref_opt;
}
if mparent.last_child == Some(self) {
mparent.last_child = previous_ref_opt;
}
}
if let Some(previous_ref) = previous_ref_opt {
let mprevious = arena.try_get_mut(previous_ref)?;
mprevious.next_sibling = next_ref_opt;
}
if let Some(next_ref) = next_ref_opt {
let mnext = arena.try_get_mut(next_ref)?;
mnext.previous_sibling = previous_ref_opt;
}
if first_ref_opt.is_some() {
let mut currentref_opt = first_ref_opt;
while let Some(current_ref) = currentref_opt {
let current = arena.try_get_mut(current_ref)?;
let nextref_opt = current.next_sibling;
current_ref.try_delete(arena)?;
currentref_opt = nextref_opt;
}
}
arena.arena[self.cell] = None;
arena.free_indicies.push(self.cell);
Ok(())
}
#[inline(always)]
pub fn merge_or_append_text(self, arena: &mut Arena, index: text::Index) {
self.try_merge_or_append_text(arena, index).unwrap();
}
pub fn try_merge_or_append_text(self, arena: &mut Arena, index: text::Index) -> Result<()> {
if let Some(last_child_ref) = arena.try_get(self)?.last_child {
if let KindData::Text(text_node) = arena.try_get_mut(last_child_ref)?.kind_data_mut() {
if let Some(s) = text_node.index() {
if s.stop() == index.start()
&& !text_node.has_qualifiers(TextQualifier::SOFT_LINE_BREAK)
&& !text_node.has_qualifiers(TextQualifier::TEMP)
{
text_node.value = (s.start(), index.stop()).into();
return Ok(());
}
}
}
}
let new_node_ref = arena.new_node(Text::new(index));
self.try_append_child(arena, new_node_ref)?;
Ok(())
}
#[inline(always)]
pub fn merge_or_insert_after_text(
self,
arena: &mut Arena,
target_ref: NodeRef,
index: text::Index,
) {
self.try_merge_or_insert_after_text(arena, target_ref, index)
.unwrap();
}
pub fn try_merge_or_insert_after_text(
self,
arena: &mut Arena,
target_ref: NodeRef,
index: text::Index,
) -> Result<()> {
if let KindData::Text(text_node) = arena.try_get_mut(target_ref)?.kind_data_mut() {
if let Some(s) = text_node.index() {
if s.stop() == index.start()
&& !text_node.has_qualifiers(TextQualifier::SOFT_LINE_BREAK)
&& !text_node.has_qualifiers(TextQualifier::TEMP)
{
text_node.value = (s.start(), index.stop()).into();
return Ok(());
}
}
}
let new_node_ref = arena.new_node(Text::new(index));
self.try_insert_after(arena, target_ref, new_node_ref)?;
Ok(())
}
#[inline(always)]
pub fn merge_or_insert_before_text(
self,
arena: &mut Arena,
target_ref: NodeRef,
index: text::Index,
) {
self.try_merge_or_insert_before_text(arena, target_ref, index)
.unwrap();
}
pub fn try_merge_or_insert_before_text(
self,
arena: &mut Arena,
target_ref: NodeRef,
index: text::Index,
) -> Result<()> {
if let KindData::Text(text_node) = arena.try_get_mut(target_ref)?.kind_data_mut() {
if let Some(s) = text_node.index() {
if s.start() == index.stop() && !text_node.has_qualifiers(TextQualifier::TEMP) {
text_node.value = (index.start(), s.stop()).into();
return Ok(());
}
}
}
let new_node_ref = arena.new_node(Text::new(index));
self.try_insert_before(arena, target_ref, new_node_ref)?;
Ok(())
}
}
#[derive(Debug, Clone, Copy)]
pub struct ArenaOptions {
pub initial_size: usize,
}
impl Default for ArenaOptions {
fn default() -> Self {
Self { initial_size: 1024 }
}
}
#[derive(Debug)]
pub struct Arena {
arena: Vec<Option<Node>>,
free_indicies: Vec<usize>,
id_seq: usize,
}
impl Default for Arena {
fn default() -> Self {
Self::with_options(ArenaOptions::default())
}
}
impl Arena {
pub fn new() -> Self {
Self::default()
}
pub fn with_options(options: ArenaOptions) -> Self {
Self {
arena: Vec::with_capacity(options.initial_size),
free_indicies: Vec::with_capacity(options.initial_size / 16),
id_seq: 0,
}
}
#[inline(always)]
pub fn get(&self, id: NodeRef) -> Option<&Node> {
self.arena.get(id.cell).and_then(|node| node.as_ref())
}
#[inline(always)]
fn try_get(&self, id: NodeRef) -> Result<&Node> {
self.arena
.get(id.cell)
.and_then(|node| node.as_ref())
.ok_or_else(|| Error::invalid_node_ref(id))
}
#[inline(always)]
pub fn get_mut(&mut self, id: NodeRef) -> Option<&mut Node> {
self.arena.get_mut(id.cell).and_then(|node| node.as_mut())
}
#[inline(always)]
fn try_get_mut(&mut self, id: NodeRef) -> Result<&mut Node> {
self.arena
.get_mut(id.cell)
.and_then(|node| node.as_mut())
.ok_or_else(|| Error::invalid_node_ref(id))
}
pub fn new_node<T: Into<KindData> + 'static>(&mut self, data: T) -> NodeRef {
let node = Node::new(data);
let cell = if let Some(index) = self.free_indicies.pop() {
self.arena[index] = Some(node);
index
} else {
let index = self.arena.len();
self.arena.push(Some(node));
index
};
let node_ref = NodeRef::new(cell, self.id_seq);
self.id_seq += 1;
node_ref
}
}
impl Index<NodeRef> for Arena {
type Output = Node;
fn index(&self, node_ref: NodeRef) -> &Self::Output {
self.arena[node_ref.cell]
.as_ref()
.expect("Invalid node reference")
}
}
impl IndexMut<NodeRef> for Arena {
fn index_mut(&mut self, node_ref: NodeRef) -> &mut Self::Output {
self.arena[node_ref.cell]
.as_mut()
.expect("Invalid node reference")
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub enum Meta {
#[default]
Null,
Bool(bool),
Int(i64),
Float(f64),
String(String),
Sequence(Vec<Meta>),
Mapping(StringMap<Meta>),
}
macro_rules! impl_meta_as {
($name: ident, $variant:ident, $ty:ty) => {
pub fn $name(&self) -> Option<&$ty> {
let Meta::$variant(v) = self else { return None };
Some(v)
}
};
}
impl Meta {
pub fn take(&mut self) -> Meta {
core::mem::replace(self, Meta::Null)
}
pub fn as_mapping_mut(&mut self) -> Option<&mut StringMap<Meta>> {
let Meta::Mapping(m) = self else { return None };
Some(m)
}
pub fn as_sequence_mut(&mut self) -> Option<&mut Vec<Meta>> {
let Meta::Sequence(s) = self else { return None };
Some(s)
}
impl_meta_as!(as_bool, Bool, bool);
impl_meta_as!(as_int, Int, i64);
impl_meta_as!(as_float, Float, f64);
impl_meta_as!(as_str, String, str);
impl_meta_as!(as_sequence, Sequence, Vec<Meta>);
impl_meta_as!(as_mapping, Mapping, StringMap<Meta>);
}
pub type Metadata = StringMap<Meta>;
pub type Attributes = StringMap<text::MultilineValue>;
#[derive(Debug)]
#[non_exhaustive]
pub enum KindData {
Document(Document),
Paragraph(Paragraph),
Heading(Heading),
ThematicBreak(ThematicBreak),
CodeBlock(CodeBlock),
Blockquote(Blockquote),
List(List),
ListItem(ListItem),
HtmlBlock(HtmlBlock),
Text(Text),
CodeSpan(CodeSpan),
Emphasis(Emphasis),
Strong(Strong),
Link(Link),
Image(Image),
RawHtml(RawHtml),
LinkReferenceDefinition(LinkReferenceDefinition),
Table(Table),
TableHeader(TableHeader),
TableBody(TableBody),
TableRow(TableRow),
TableCell(TableCell),
Strikethrough(Strikethrough),
Extension(Box<dyn ExtensionData>),
}
impl KindData {
pub fn typ(&self) -> NodeType {
match self {
KindData::Document(n) => n.typ(),
KindData::Paragraph(n) => n.typ(),
KindData::Heading(n) => n.typ(),
KindData::ThematicBreak(n) => n.typ(),
KindData::CodeBlock(n) => n.typ(),
KindData::Blockquote(n) => n.typ(),
KindData::List(n) => n.typ(),
KindData::ListItem(n) => n.typ(),
KindData::HtmlBlock(n) => n.typ(),
KindData::Text(n) => n.typ(),
KindData::CodeSpan(n) => n.typ(),
KindData::Emphasis(n) => n.typ(),
KindData::Strong(n) => n.typ(),
KindData::Link(n) => n.typ(),
KindData::Image(n) => n.typ(),
KindData::RawHtml(n) => n.typ(),
KindData::LinkReferenceDefinition(n) => n.typ(),
KindData::Table(n) => n.typ(),
KindData::TableHeader(n) => n.typ(),
KindData::TableBody(n) => n.typ(),
KindData::TableRow(n) => n.typ(),
KindData::TableCell(n) => n.typ(),
KindData::Strikethrough(n) => n.typ(),
KindData::Extension(n) => n.typ(),
}
}
pub fn kind_name(&self) -> &'static str {
match self {
KindData::Document(n) => n.kind_name(),
KindData::Paragraph(n) => n.kind_name(),
KindData::Heading(n) => n.kind_name(),
KindData::ThematicBreak(n) => n.kind_name(),
KindData::CodeBlock(n) => n.kind_name(),
KindData::Blockquote(n) => n.kind_name(),
KindData::List(n) => n.kind_name(),
KindData::ListItem(n) => n.kind_name(),
KindData::HtmlBlock(n) => n.kind_name(),
KindData::Text(n) => n.kind_name(),
KindData::CodeSpan(n) => n.kind_name(),
KindData::Emphasis(n) => n.kind_name(),
KindData::Strong(n) => n.kind_name(),
KindData::Link(n) => n.kind_name(),
KindData::Image(n) => n.kind_name(),
KindData::RawHtml(n) => n.kind_name(),
KindData::LinkReferenceDefinition(n) => n.kind_name(),
KindData::Table(n) => n.kind_name(),
KindData::TableHeader(n) => n.kind_name(),
KindData::TableBody(n) => n.kind_name(),
KindData::TableRow(n) => n.kind_name(),
KindData::TableCell(n) => n.kind_name(),
KindData::Strikethrough(n) => n.kind_name(),
KindData::Extension(n) => n.kind_name(),
}
}
pub fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
match self {
KindData::Document(n) => n.pretty_print(w, source, level),
KindData::Paragraph(n) => n.pretty_print(w, source, level),
KindData::Heading(n) => n.pretty_print(w, source, level),
KindData::ThematicBreak(n) => n.pretty_print(w, source, level),
KindData::CodeBlock(n) => n.pretty_print(w, source, level),
KindData::Blockquote(n) => n.pretty_print(w, source, level),
KindData::List(n) => n.pretty_print(w, source, level),
KindData::ListItem(n) => n.pretty_print(w, source, level),
KindData::HtmlBlock(n) => n.pretty_print(w, source, level),
KindData::Text(n) => n.pretty_print(w, source, level),
KindData::CodeSpan(n) => n.pretty_print(w, source, level),
KindData::Emphasis(n) => n.pretty_print(w, source, level),
KindData::Strong(n) => n.pretty_print(w, source, level),
KindData::Link(n) => n.pretty_print(w, source, level),
KindData::Image(n) => n.pretty_print(w, source, level),
KindData::RawHtml(n) => n.pretty_print(w, source, level),
KindData::LinkReferenceDefinition(n) => n.pretty_print(w, source, level),
KindData::Table(n) => n.pretty_print(w, source, level),
KindData::TableHeader(n) => n.pretty_print(w, source, level),
KindData::TableBody(n) => n.pretty_print(w, source, level),
KindData::TableRow(n) => n.pretty_print(w, source, level),
KindData::TableCell(n) => n.pretty_print(w, source, level),
KindData::Strikethrough(n) => n.pretty_print(w, source, level),
KindData::Extension(n) => n.pretty_print(w, source, level),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[non_exhaustive]
pub enum NodeType {
ContainerBlock,
LeafBlock,
Inline,
}
impl From<NodeType> for TypeData {
fn from(t: NodeType) -> Self {
match t {
NodeType::ContainerBlock => TypeData::Block(Block {
btype: BlockType::Container,
..Default::default()
}),
NodeType::LeafBlock => TypeData::Block(Block {
btype: BlockType::Leaf,
..Default::default()
}),
NodeType::Inline => TypeData::Inline(Inline::default()),
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum TypeData {
Block(Block),
Inline(Inline),
}
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum BlockType {
Container,
Leaf,
}
#[derive(Debug)]
pub struct Block {
btype: BlockType,
source: Option<Vec<text::Segment>>,
has_blank_previous_line: bool,
}
impl Default for Block {
fn default() -> Self {
Self {
btype: BlockType::Container,
source: None,
has_blank_previous_line: false,
}
}
}
impl Block {
#[inline(always)]
pub fn is_container(&self) -> bool {
self.btype == BlockType::Container
}
#[inline(always)]
pub fn is_leaf(&self) -> bool {
self.btype == BlockType::Leaf
}
pub fn take_source(&mut self) -> Vec<text::Segment> {
self.source.take().unwrap_or_default()
}
pub fn put_back_source(&mut self, source: Vec<text::Segment>) {
self.source = Some(source);
}
#[inline(always)]
pub fn source(&self) -> &text::Block {
self.source.as_deref().unwrap_or(&[])
}
#[inline(always)]
pub fn append_source_line(&mut self, line: text::Segment) {
if let Some(source) = &mut self.source {
source.push(line);
} else {
self.source = Some(Vec::with_capacity(16));
self.source.as_mut().unwrap().push(line);
}
}
#[inline(always)]
pub fn append_source_lines(&mut self, lines: &text::Block) {
if let Some(source) = &mut self.source {
source.extend_from_slice(lines);
} else {
self.source = Some(lines.to_vec());
}
}
#[inline(always)]
pub fn replace_source_line(&mut self, index: usize, line: text::Segment) {
if let Some(source) = &mut self.source {
if index < source.len() {
source[index] = line;
}
}
}
#[inline(always)]
pub fn remove_source_line(&mut self, index: usize) {
if let Some(source) = &mut self.source {
if index < source.len() {
source.remove(index);
}
}
}
#[inline(always)]
pub fn has_blank_previous_line(&self) -> bool {
self.has_blank_previous_line
}
#[inline(always)]
pub fn set_blank_previous_line(&mut self, value: bool) {
self.has_blank_previous_line = value;
}
}
#[derive(Debug, Default)]
pub struct Inline {}
#[derive(Debug)]
pub struct Node {
kind_data: KindData,
type_data: TypeData,
parent: Option<NodeRef>,
first_child: Option<NodeRef>,
next_sibling: Option<NodeRef>,
previous_sibling: Option<NodeRef>,
last_child: Option<NodeRef>,
attributes: Attributes,
pos: Option<usize>,
}
impl Node {
pub fn new<T: Into<KindData> + 'static>(data: T) -> Self {
let d: KindData = data.into();
let t: NodeType = d.typ();
Self {
kind_data: d,
type_data: t.into(),
parent: None,
first_child: None,
next_sibling: None,
previous_sibling: None,
last_child: None,
attributes: Attributes::new(),
pos: None,
}
}
pub fn kind_data(&self) -> &KindData {
&self.kind_data
}
pub fn kind_data_mut(&mut self) -> &mut KindData {
&mut self.kind_data
}
pub fn type_data(&self) -> &TypeData {
&self.type_data
}
pub fn type_data_mut(&mut self) -> &mut TypeData {
&mut self.type_data
}
#[inline(always)]
pub fn parent(&self) -> Option<NodeRef> {
self.parent
}
#[inline(always)]
pub fn set_parent(&mut self, parent: NodeRef) {
self.parent = Some(parent);
}
#[inline(always)]
pub fn first_child(&self) -> Option<NodeRef> {
self.first_child
}
#[inline(always)]
pub fn has_children(&self) -> bool {
self.first_child.is_some()
}
#[inline(always)]
pub fn set_first_child(&mut self, child: NodeRef) {
self.first_child = Some(child);
}
#[inline(always)]
pub fn next_sibling(&self) -> Option<NodeRef> {
self.next_sibling
}
#[inline(always)]
pub fn set_next_sibling(&mut self, sibling: NodeRef) {
self.next_sibling = Some(sibling);
}
#[inline(always)]
pub fn previous_sibling(&self) -> Option<NodeRef> {
self.previous_sibling
}
#[inline(always)]
pub fn set_previous_sibling(&mut self, sibling: NodeRef) {
self.previous_sibling = Some(sibling);
}
#[inline(always)]
pub fn last_child(&self) -> Option<NodeRef> {
self.last_child
}
#[inline(always)]
pub fn set_last_child(&mut self, child: NodeRef) {
self.last_child = Some(child);
}
#[inline(always)]
pub fn children<'a>(&self, arena: &'a Arena) -> Siblings<'a> {
Siblings {
arena,
front: self.first_child,
back: self.last_child,
}
}
#[inline(always)]
pub fn children_mut(&self, arena: &Arena) -> NodesMut {
NodesMut::with_vec(self.children(arena).collect())
}
#[inline(always)]
pub fn attributes(&self) -> &Attributes {
&self.attributes
}
#[inline(always)]
pub fn attributes_mut(&mut self) -> &mut Attributes {
&mut self.attributes
}
#[inline(always)]
pub fn set_pos(&mut self, pos: usize) {
self.pos = Some(pos);
}
pub(crate) fn has_pos(&self) -> bool {
self.pos.is_some()
}
#[inline(always)]
pub fn pos(&self) -> Option<usize> {
match &self.kind_data() {
KindData::Text(n) => n.index().map(|i| i.start()),
_ => self.pos,
}
}
pub fn owner_document(&self, arena: &Arena) -> Option<NodeRef> {
let mut current = self.parent?;
while let Some(parent) = arena.get(current)?.parent {
current = parent;
}
if matches!(arena[current].kind_data(), KindData::Document(_)) {
Some(current)
} else {
None
}
}
}
pub struct Siblings<'a> {
arena: &'a Arena,
front: Option<NodeRef>,
back: Option<NodeRef>,
}
impl Iterator for Siblings<'_> {
type Item = NodeRef;
fn next(&mut self) -> Option<Self::Item> {
if let Some(current) = self.front {
let node = self.arena.get(current)?;
self.front = node.next_sibling;
if self.back.is_none() {
self.back = Some(current);
}
Some(current)
} else {
None
}
}
}
impl DoubleEndedIterator for Siblings<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
if let Some(current) = self.back {
let node = self.arena.get(current)?;
self.back = node.previous_sibling;
if self.front.is_none() {
self.front = Some(current);
}
Some(current)
} else {
None
}
}
}
pub struct NodesMut {
iter: vec::IntoIter<NodeRef>,
}
impl NodesMut {
fn with_vec(vec: Vec<NodeRef>) -> Self {
NodesMut {
iter: vec.into_iter(),
}
}
}
impl Iterator for NodesMut {
type Item = NodeRef;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl DoubleEndedIterator for NodesMut {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
pub trait PrettyPrint {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result;
}
pub trait NodeKind {
fn typ(&self) -> NodeType;
fn kind_name(&self) -> &'static str;
}
fn pp(
w: &mut dyn Write,
arena: &Arena,
node_ref: NodeRef,
source: &str,
level: usize,
) -> fmt::Result {
let indent = pp_indent(level);
{
let node = arena.get(node_ref).ok_or(fmt::Error)?;
writeln!(w, "{}{} {{", indent, node.kind_data.kind_name())?;
node.kind_data.pretty_print(w, source, level + 1)?;
}
let indent2 = pp_indent(level + 1);
let indent3 = pp_indent(level + 2);
writeln!(w, "{}Ref: {}", indent2, node_ref)?;
writeln!(
w,
"{}Pos: {}",
indent2,
arena[node_ref]
.pos()
.map_or(String::from("None"), |p| format!("{}", p))
)?;
if let TypeData::Block(block) = arena[node_ref].type_data() {
if block.source().is_empty() {
writeln!(w, "{}Source: []", indent2)?;
} else {
writeln!(w, "{}Source: [", indent2)?;
let mut nr = false;
for line in block.source() {
let l = line.str(source);
write!(w, "{}{}", indent3, l)?;
nr = l.ends_with('\n') || l.ends_with('\r');
}
if !nr {
writeln!(w)?;
}
writeln!(w, "{}]", indent2)?;
}
if block.has_blank_previous_line() {
writeln!(w, "{}HasBlankPreviousLine: true", indent2)?;
} else {
writeln!(w, "{}HasBlankPreviousLine: false", indent2)?;
}
}
if !arena[node_ref].attributes().is_empty() {
write!(w, "{}Attributes ", indent2)?;
writeln!(w, "{{")?;
for (key, value) in arena[node_ref].attributes() {
write!(w, "{}{}: ", indent3, key)?;
writeln!(w, "{}", value.str(source))?;
}
write!(w, "{}", indent2)?;
writeln!(w, "}}")?;
}
for child in arena[node_ref].children(arena) {
pp(w, arena, child, source, level + 1)?;
}
write!(w, "{}", indent)?;
writeln!(w, "}}")
}
pub fn pretty_print(
w: &mut dyn Write,
arena: &Arena,
node_ref: NodeRef,
source: &str,
) -> fmt::Result {
pp(w, arena, node_ref, source, 0)
}
pub fn pp_indent(level: usize) -> String {
" ".repeat(level)
}
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum WalkStatus {
Stop,
SkipChildren,
Continue,
Ok,
}
pub trait Walk<E> {
fn walk(
&mut self,
arena: &Arena,
node_ref: NodeRef,
entering: bool,
) -> CoreResult<WalkStatus, E>;
}
impl<F, E> Walk<E> for F
where
F: FnMut(&Arena, NodeRef, bool) -> CoreResult<WalkStatus, E>,
{
fn walk(
&mut self,
arena: &Arena,
node_ref: NodeRef,
entering: bool,
) -> CoreResult<WalkStatus, E> {
self(arena, node_ref, entering)
}
}
pub fn walk<E: CoreError + 'static>(
arena: &Arena,
node_ref: NodeRef,
walker: &mut impl Walk<E>,
) -> CoreResult<WalkStatus, CallbackError<E>> {
let status = walker
.walk(arena, node_ref, true)
.map_err(CallbackError::Callback)?;
if status == WalkStatus::Stop {
return Ok(WalkStatus::Stop);
}
if status != WalkStatus::SkipChildren {
let node = arena.try_get(node_ref).map_err(CallbackError::Internal)?;
let mut child_opt = node.first_child();
while let Some(child_ref) = child_opt {
let child_node = arena.try_get(child_ref).map_err(CallbackError::Internal)?;
if walk(arena, child_ref, walker)? == WalkStatus::Stop {
return Ok(WalkStatus::Stop);
}
child_opt = child_node.next_sibling();
}
}
if walker
.walk(arena, node_ref, false)
.map_err(CallbackError::Callback)?
== WalkStatus::Stop
{
return Ok(WalkStatus::Stop);
}
Ok(WalkStatus::Ok)
}
#[derive(Debug)]
pub struct Document {
meta: Metadata,
}
impl Default for Document {
fn default() -> Self {
Self {
meta: Metadata::new(),
}
}
}
impl Document {
pub fn new() -> Self {
Self::default()
}
#[inline(always)]
pub fn metadata(&self) -> &Metadata {
&self.meta
}
#[inline(always)]
pub fn metadata_mut(&mut self) -> &mut Metadata {
&mut self.meta
}
}
impl NodeKind for Document {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"Document"
}
}
impl PrettyPrint for Document {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Document> for KindData {
fn from(data: Document) -> Self {
KindData::Document(data)
}
}
#[derive(Debug, Default)]
pub struct Paragraph {}
impl Paragraph {
pub fn new() -> Self {
Self::default()
}
}
impl NodeKind for Paragraph {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"Paragraph"
}
}
impl PrettyPrint for Paragraph {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Paragraph> for KindData {
fn from(data: Paragraph) -> Self {
KindData::Paragraph(data)
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
#[non_exhaustive]
pub enum HeadingKind {
#[default]
Atx,
Setext,
}
#[derive(Debug, Default)]
pub struct Heading {
heading_kind: HeadingKind,
level: u8,
}
impl Heading {
pub fn new(heading_kind: HeadingKind, level: u8) -> Self {
Self {
heading_kind,
level,
}
}
#[inline(always)]
pub fn level(&self) -> u8 {
self.level
}
#[inline(always)]
pub fn heading_kind(&self) -> HeadingKind {
self.heading_kind
}
}
impl NodeKind for Heading {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"Heading"
}
}
impl PrettyPrint for Heading {
fn pretty_print(&self, w: &mut dyn Write, _source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Level: {}", pp_indent(level), self.level())
}
}
impl From<Heading> for KindData {
fn from(data: Heading) -> Self {
KindData::Heading(data)
}
}
#[derive(Debug, Default)]
pub struct ThematicBreak {}
impl ThematicBreak {
pub fn new() -> Self {
Self::default()
}
}
impl NodeKind for ThematicBreak {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"ThematicBreak"
}
}
impl PrettyPrint for ThematicBreak {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<ThematicBreak> for KindData {
fn from(data: ThematicBreak) -> Self {
KindData::ThematicBreak(data)
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[non_exhaustive]
pub enum CodeBlockKind {
Indented,
Fenced,
}
#[derive(Debug)]
pub(crate) struct FenceData {
pub char: u8,
pub indent: usize,
pub length: usize,
}
#[derive(Debug)]
pub struct CodeBlock {
code_block_kind: CodeBlockKind,
info: Option<text::Value>,
fdata: Option<FenceData>,
value: text::Lines,
}
impl CodeBlock {
pub fn new(code_block_kind: CodeBlockKind, info: Option<text::Value>) -> Self {
Self {
code_block_kind,
info,
fdata: None,
value: text::Lines::default(),
}
}
#[inline(always)]
pub fn code_block_kind(&self) -> CodeBlockKind {
self.code_block_kind
}
#[inline(always)]
pub fn value(&self) -> &text::Lines {
&self.value
}
#[inline(always)]
pub fn set_value(&mut self, value: impl Into<text::Lines>) {
self.value = value.into();
}
pub(crate) fn fence_data(&self) -> Option<&FenceData> {
self.fdata.as_ref()
}
pub(crate) fn set_fence_data(&mut self, fdata: FenceData) {
self.fdata = Some(fdata);
}
#[inline(always)]
pub fn info_str<'a>(&'a self, source: &'a str) -> Option<&'a str> {
match &self.info {
Some(info) => Some(info.str(source)),
None => None,
}
}
#[inline(always)]
pub fn info(&self) -> Option<&text::Value> {
self.info.as_ref()
}
pub fn language_str<'a>(&'a self, source: &'a str) -> Option<&'a str> {
match &self.info {
Some(info) => {
let info_str = info.str(source);
info_str
.find(' ')
.map(|i| &info_str[..i])
.or(Some(info_str))
}
None => None,
}
}
}
impl NodeKind for CodeBlock {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"CodeBlock"
}
}
impl PrettyPrint for CodeBlock {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(
w,
"{}CodeBlockKind: {}",
pp_indent(level),
match self.code_block_kind {
CodeBlockKind::Indented => "Indented",
CodeBlockKind::Fenced => "Fenced",
}
)?;
writeln!(
w,
"{}Info: {}",
pp_indent(level),
match self.info_str(source) {
Some(info) => info,
None => &"<none>",
}
)?;
write!(w, "{}Value: ", pp_indent(level))?;
writeln!(w, "[ ")?;
for line in self.value.iter(source) {
write!(w, "{}{}", pp_indent(level + 1), line)?;
}
writeln!(w)?;
writeln!(w, "{}]", pp_indent(level))
}
}
impl From<CodeBlock> for KindData {
fn from(data: CodeBlock) -> Self {
KindData::CodeBlock(data)
}
}
#[derive(Debug, Default)]
pub struct Blockquote {}
impl Blockquote {
pub fn new() -> Self {
Self::default()
}
}
impl NodeKind for Blockquote {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"Blockquote"
}
}
impl PrettyPrint for Blockquote {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Blockquote> for KindData {
fn from(data: Blockquote) -> Self {
KindData::Blockquote(data)
}
}
#[derive(Debug, Default)]
pub struct List {
marker: u8,
is_tight: bool,
start: u32,
}
impl List {
pub fn new(marker: u8) -> Self {
Self {
marker,
is_tight: true,
start: 0,
}
}
#[inline(always)]
pub fn is_ordered(&self) -> bool {
self.marker == b'.' || self.marker == b')'
}
pub fn can_continue(&self, marker: u8, is_ordered: bool) -> bool {
marker == self.marker && is_ordered == self.is_ordered()
}
#[inline(always)]
pub fn marker(&self) -> u8 {
self.marker
}
#[inline(always)]
pub fn is_tight(&self) -> bool {
self.is_tight
}
#[inline(always)]
pub fn set_tight(&mut self, tight: bool) {
self.is_tight = tight;
}
#[inline(always)]
pub fn start(&self) -> u32 {
self.start
}
#[inline(always)]
pub fn set_start(&mut self, start: u32) {
self.start = start;
}
}
impl NodeKind for List {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"List"
}
}
impl PrettyPrint for List {
fn pretty_print(&self, w: &mut dyn Write, _source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Marker: '{}'", pp_indent(level), self.marker() as char)?;
writeln!(w, "{}IsTight: {}", pp_indent(level), self.is_tight())?;
writeln!(w, "{}Start: {}", pp_indent(level), self.start())
}
}
impl From<List> for KindData {
fn from(data: List) -> Self {
KindData::List(data)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Task {
Active,
Completed,
}
impl Display for Task {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Task::Active => write!(f, "Active"),
Task::Completed => write!(f, "Completed"),
}
}
}
#[derive(Debug, Default)]
pub struct ListItem {
offset: usize,
task: Option<Task>,
}
impl ListItem {
pub fn new() -> Self {
Self::default()
}
pub(crate) fn with_offset(offset: usize) -> Self {
Self { offset, task: None }
}
#[inline(always)]
pub(crate) fn offset(&self) -> usize {
self.offset
}
#[inline(always)]
pub fn is_task(&self) -> bool {
self.task.is_some()
}
#[inline(always)]
pub fn task(&self) -> Option<Task> {
self.task
}
#[inline(always)]
pub fn set_task(&mut self, task: Option<Task>) {
self.task = task;
}
}
impl NodeKind for ListItem {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"ListItem"
}
}
impl PrettyPrint for ListItem {
fn pretty_print(&self, w: &mut dyn Write, _source: &str, level: usize) -> fmt::Result {
if self.offset() > 0 {
writeln!(w, "{}Offset: {}", pp_indent(level), self.offset())?;
}
if self.is_task() {
writeln!(w, "{}Task: {}", pp_indent(level), self.task().unwrap())
} else {
Ok(())
}
}
}
impl From<ListItem> for KindData {
fn from(data: ListItem) -> Self {
KindData::ListItem(data)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum HtmlBlockKind {
Kind1,
Kind2,
Kind3,
Kind4,
Kind5,
Kind6,
Kind7,
}
impl Display for HtmlBlockKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
HtmlBlockKind::Kind1 => write!(f, "Kind1"),
HtmlBlockKind::Kind2 => write!(f, "Kind2"),
HtmlBlockKind::Kind3 => write!(f, "Kind3"),
HtmlBlockKind::Kind4 => write!(f, "Kind4"),
HtmlBlockKind::Kind5 => write!(f, "Kind5"),
HtmlBlockKind::Kind6 => write!(f, "Kind6"),
HtmlBlockKind::Kind7 => write!(f, "Kind7"),
}
}
}
#[derive(Debug)]
pub struct HtmlBlock {
html_block_kind: HtmlBlockKind,
value: text::Lines,
}
impl HtmlBlock {
pub fn new(typ: HtmlBlockKind) -> Self {
Self {
html_block_kind: typ,
value: text::Lines::default(),
}
}
#[inline(always)]
pub fn value(&self) -> &text::Lines {
&self.value
}
#[inline(always)]
pub fn set_value(&mut self, value: impl Into<text::Lines>) {
self.value = value.into();
}
#[inline(always)]
pub fn html_block_kind(&self) -> HtmlBlockKind {
self.html_block_kind
}
}
impl NodeKind for HtmlBlock {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"HtmlBlock"
}
}
impl PrettyPrint for HtmlBlock {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(
w,
"{}HtmlBlockKind: {}",
pp_indent(level),
self.html_block_kind()
)?;
write!(w, "{}Value: ", pp_indent(level))?;
writeln!(w, "[ ")?;
for line in self.value.iter(source) {
write!(w, "{}{}", pp_indent(level + 1), line)?;
}
writeln!(w)?;
writeln!(w, "{}]", pp_indent(level))
}
}
impl From<HtmlBlock> for KindData {
fn from(data: HtmlBlock) -> Self {
KindData::HtmlBlock(data)
}
}
#[derive(Debug)]
pub struct LinkReferenceDefinition {
label: text::MultilineValue,
destination: text::Value,
title: Option<text::MultilineValue>,
}
impl LinkReferenceDefinition {
pub fn new(
label: impl Into<text::MultilineValue>,
destination: impl Into<text::Value>,
) -> Self {
Self {
label: label.into(),
destination: destination.into(),
title: None,
}
}
pub fn with_title(
label: impl Into<text::MultilineValue>,
destination: impl Into<text::Value>,
title: impl Into<text::MultilineValue>,
) -> Self {
Self {
label: label.into(),
destination: destination.into(),
title: Some(title.into()),
}
}
#[inline(always)]
pub fn label(&self) -> &text::MultilineValue {
&self.label
}
#[inline(always)]
pub fn label_str<'a>(&'a self, source: &'a str) -> Cow<'a, str> {
self.label.str(source)
}
#[inline(always)]
pub fn destination(&self) -> &text::Value {
&self.destination
}
#[inline(always)]
pub fn destination_str<'a>(&'a self, source: &'a str) -> &'a str {
self.destination.str(source)
}
#[inline(always)]
pub fn title(&self) -> Option<&text::MultilineValue> {
self.title.as_ref()
}
#[inline(always)]
pub fn title_str<'a>(&'a self, source: &'a str) -> Option<Cow<'a, str>> {
self.title.as_ref().map(|t| t.str(source))
}
}
impl NodeKind for LinkReferenceDefinition {
fn typ(&self) -> NodeType {
NodeType::LeafBlock
}
fn kind_name(&self) -> &'static str {
"LinkReferenceDefinition"
}
}
impl PrettyPrint for LinkReferenceDefinition {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Label: {}", pp_indent(level), self.label.str(source))?;
writeln!(
w,
"{}Destination: {}",
pp_indent(level),
self.destination.str(source)
)?;
writeln!(
w,
"{}Title: {}",
pp_indent(level),
self.title_str(source).as_deref().unwrap_or("<None>")
)
}
}
impl From<LinkReferenceDefinition> for KindData {
fn from(data: LinkReferenceDefinition) -> Self {
KindData::LinkReferenceDefinition(data)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum TableCellAlignment {
Left,
Center,
Right,
None,
}
impl TableCellAlignment {
pub fn as_str(&self) -> &'static str {
match self {
TableCellAlignment::Left => "left",
TableCellAlignment::Center => "center",
TableCellAlignment::Right => "right",
TableCellAlignment::None => "none",
}
}
}
#[derive(Debug, Default)]
pub struct Table {}
impl Table {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for Table {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"Table"
}
}
impl PrettyPrint for Table {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Table> for KindData {
fn from(e: Table) -> Self {
KindData::Table(e)
}
}
#[derive(Debug, Default)]
pub struct TableRow {}
impl TableRow {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for TableRow {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"TableRow"
}
}
impl PrettyPrint for TableRow {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<TableRow> for KindData {
fn from(e: TableRow) -> Self {
KindData::TableRow(e)
}
}
#[derive(Debug, Default)]
pub struct TableHeader {}
impl TableHeader {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for TableHeader {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"TableHeader"
}
}
impl PrettyPrint for TableHeader {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<TableHeader> for KindData {
fn from(e: TableHeader) -> Self {
KindData::TableHeader(e)
}
}
#[derive(Debug, Default)]
pub struct TableBody {}
impl TableBody {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for TableBody {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"TableBody"
}
}
impl PrettyPrint for TableBody {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<TableBody> for KindData {
fn from(e: TableBody) -> Self {
KindData::TableBody(e)
}
}
#[derive(Debug)]
pub struct TableCell {
alignment: TableCellAlignment,
}
impl Default for TableCell {
fn default() -> Self {
Self {
alignment: TableCellAlignment::None,
}
}
}
impl TableCell {
pub fn new() -> Self {
Self::default()
}
pub fn with_alignment(alignment: TableCellAlignment) -> Self {
Self { alignment }
}
#[inline(always)]
pub fn alignment(&self) -> TableCellAlignment {
self.alignment
}
}
impl NodeKind for TableCell {
fn typ(&self) -> NodeType {
NodeType::ContainerBlock
}
fn kind_name(&self) -> &'static str {
"TableCell"
}
}
impl PrettyPrint for TableCell {
fn pretty_print(&self, w: &mut dyn Write, _source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Alignment: {:?}", pp_indent(level), self.alignment,)
}
}
impl From<TableCell> for KindData {
fn from(e: TableCell) -> Self {
KindData::TableCell(e)
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct TextQualifier: u16 {
const SOFT_LINE_BREAK = 1 << 0;
const HARD_LINE_BREAK = 1 << 1;
const TEMP = 1 << 2;
}
}
#[derive(Debug)]
pub struct Text {
value: text::Value,
qualifiers: TextQualifier,
}
impl Text {
pub fn new(textual: impl Into<text::Value>) -> Self {
let qualifiers = TextQualifier::default();
Self {
value: textual.into(),
qualifiers,
}
}
pub fn with_qualifiers(textual: impl Into<text::Value>, qualifiers: TextQualifier) -> Self {
Self {
value: textual.into(),
qualifiers,
}
}
#[inline(always)]
pub fn index(&self) -> Option<&text::Index> {
match &self.value {
text::Value::Index(idx) => Some(idx),
_ => None,
}
}
#[inline(always)]
pub fn set(&mut self, value: impl Into<text::Value>) {
self.value = value.into();
}
pub fn add_qualifiers(&mut self, qualifiers: TextQualifier) {
self.qualifiers |= qualifiers;
}
pub fn has_qualifiers(&self, qualifiers: TextQualifier) -> bool {
self.qualifiers.contains(qualifiers)
}
pub fn bytes<'a>(&'a self, source: &'a str) -> &'a [u8] {
self.value.bytes(source)
}
pub fn str<'a>(&'a self, source: &'a str) -> &'a str {
self.value.str(source)
}
}
impl NodeKind for Text {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Text"
}
}
impl PrettyPrint for Text {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Qualifiers: {:?}", pp_indent(level), self.qualifiers)?;
writeln!(w, "{}Content: '{}'", pp_indent(level), self.str(source))
}
}
impl From<Text> for KindData {
fn from(data: Text) -> Self {
KindData::Text(data)
}
}
#[derive(Debug)]
enum CodeSpanValue {
Indices(TinyVec<text::Index>),
String(String),
}
#[derive(Debug)]
pub struct CodeSpan {
value: CodeSpanValue,
}
impl CodeSpan {
pub fn empty() -> Self {
Self {
value: CodeSpanValue::Indices(TinyVec::empty()),
}
}
pub fn from_indices(indices: impl Into<TinyVec<text::Index>>) -> Self {
Self {
value: CodeSpanValue::Indices(indices.into()),
}
}
pub fn from_string(value: impl Into<String>) -> Self {
Self {
value: CodeSpanValue::String(value.into()),
}
}
pub(crate) fn indices(&self) -> Option<&[text::Index]> {
match &self.value {
CodeSpanValue::Indices(indices) => Some(indices.as_slice()),
_ => None,
}
}
pub fn str<'a>(&'a self, source: &'a str) -> Cow<'a, str> {
match &self.value {
CodeSpanValue::Indices(indices) => {
if indices.is_empty() {
Cow::Borrowed("")
} else if indices.len() == 1 {
let idx = indices[0];
if source.as_bytes()[idx.stop() - 1] != b'\n' {
Cow::Borrowed(idx.str(source))
} else {
let idx: text::Index = (idx.start(), idx.stop() - 1).into();
let s = idx.str(source);
let mut st = String::with_capacity(s.len() + 1);
st.push_str(s);
st.push(' ');
Cow::Owned(st)
}
} else {
let mut s = String::new();
for idx in indices.iter() {
s.push_str(idx.str(source));
}
Cow::Owned(s.replace('\n', " "))
}
}
CodeSpanValue::String(s) => {
if memchr::memchr(b'\n', s.as_bytes()).is_some() {
Cow::Owned(s.replace('\n', " "))
} else {
Cow::Borrowed(s)
}
}
}
}
}
impl NodeKind for CodeSpan {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"CodeSpan"
}
}
impl PrettyPrint for CodeSpan {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<CodeSpan> for KindData {
fn from(data: CodeSpan) -> Self {
KindData::CodeSpan(data)
}
}
#[derive(Debug, Default)]
pub struct Emphasis {}
impl Emphasis {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for Emphasis {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Emphasis"
}
}
impl PrettyPrint for Emphasis {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Emphasis> for KindData {
fn from(data: Emphasis) -> Self {
KindData::Emphasis(data)
}
}
#[derive(Debug, Default)]
pub struct Strong {}
impl Strong {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for Strong {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Strong"
}
}
impl PrettyPrint for Strong {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Strong> for KindData {
fn from(data: Strong) -> Self {
KindData::Strong(data)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum LinkKind {
Inline,
Reference(LinkReference),
Auto(AutoLink),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum LinkReferenceKind {
Full,
Collapsed,
Shortcut,
}
#[derive(Debug)]
pub struct LinkReference {
value: text::MultilineValue,
link_reference_kind: LinkReferenceKind,
}
impl LinkReference {
#[inline(always)]
pub fn value_str<'a>(&'a self, source: &'a str) -> Cow<'a, str> {
self.value.str(source)
}
#[inline(always)]
pub fn value(&self) -> &text::MultilineValue {
&self.value
}
#[inline(always)]
pub fn link_reference_kind(&self) -> LinkReferenceKind {
self.link_reference_kind
}
}
#[derive(Debug)]
pub struct AutoLink {
text: text::Value,
}
impl AutoLink {
#[inline(always)]
pub fn text_str<'a>(&'a self, source: &'a str) -> &'a str {
self.text.str(source)
}
#[inline(always)]
pub fn text(&self) -> &text::Value {
&self.text
}
}
#[derive(Debug)]
pub struct Link {
destination: text::Value,
title: Option<text::MultilineValue>,
link_kind: LinkKind,
}
impl Link {
pub fn inline(destination: impl Into<text::Value>) -> Self {
Self {
destination: destination.into(),
title: None,
link_kind: LinkKind::Inline,
}
}
pub fn inline_with_title(
destination: impl Into<text::Value>,
title: impl Into<text::MultilineValue>,
) -> Self {
Self {
destination: destination.into(),
title: Some(title.into()),
link_kind: LinkKind::Inline,
}
}
pub fn reference(
destination: impl Into<text::Value>,
value: impl Into<text::MultilineValue>,
reference_kind: LinkReferenceKind,
) -> Self {
Self {
destination: destination.into(),
title: None,
link_kind: LinkKind::Reference(LinkReference {
value: value.into(),
link_reference_kind: reference_kind,
}),
}
}
pub fn reference_with_title(
destination: impl Into<text::Value>,
value: impl Into<text::MultilineValue>,
reference_kind: LinkReferenceKind,
title: impl Into<text::MultilineValue>,
) -> Self {
Self {
destination: destination.into(),
title: Some(title.into()),
link_kind: LinkKind::Reference(LinkReference {
value: value.into(),
link_reference_kind: reference_kind,
}),
}
}
pub fn auto(destination: impl Into<text::Value>, text: impl Into<text::Value>) -> Self {
Self {
destination: destination.into(),
title: None,
link_kind: LinkKind::Auto(AutoLink { text: text.into() }),
}
}
#[inline(always)]
pub fn destination(&self) -> &text::Value {
&self.destination
}
#[inline(always)]
pub fn destination_str<'a>(&'a self, source: &'a str) -> &'a str {
self.destination.str(source)
}
#[inline(always)]
pub fn title(&self) -> Option<&text::MultilineValue> {
self.title.as_ref()
}
#[inline(always)]
pub fn title_str<'a>(&'a self, source: &'a str) -> Option<Cow<'a, str>> {
self.title.as_ref().map(|t| t.str(source))
}
#[inline(always)]
pub fn link_kind(&self) -> &LinkKind {
&self.link_kind
}
}
impl NodeKind for Link {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Link"
}
}
impl PrettyPrint for Link {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
match self.link_kind() {
LinkKind::Inline => writeln!(w, "{}LinkKind: Inline", pp_indent(level))?,
LinkKind::Reference(reference) => {
writeln!(w, "{}LinkKind: Reference", pp_indent(level))?;
writeln!(
w,
"{}ReferenceLabel: {}",
pp_indent(level),
reference.value.str(source)
)?;
writeln!(
w,
"{}ReferenceKind: {:?}",
pp_indent(level),
reference.link_reference_kind
)?;
}
LinkKind::Auto(auto) => {
writeln!(w, "{}LinkKind: Auto", pp_indent(level))?;
writeln!(
w,
"{}AutoLinkText: {}",
pp_indent(level),
auto.text.str(source)
)?;
}
}
writeln!(
w,
"{}Destination: {}",
pp_indent(level),
self.destination.str(source)
)?;
if let Some(title) = &self.title {
writeln!(w, "{}Title: {}", pp_indent(level), title.str(source))?;
}
Ok(())
}
}
impl From<Link> for KindData {
fn from(data: Link) -> Self {
KindData::Link(data)
}
}
#[derive(Debug)]
pub struct Image {
destination: text::Value,
title: Option<text::MultilineValue>,
link_kind: LinkKind,
}
impl Image {
pub(crate) fn from_link(link: Link) -> Self {
Self {
destination: link.destination,
title: link.title,
link_kind: link.link_kind,
}
}
pub fn inline(destination: impl Into<text::Value>) -> Self {
Self {
destination: destination.into(),
title: None,
link_kind: LinkKind::Inline,
}
}
pub fn inline_with_title(
destination: impl Into<text::Value>,
title: impl Into<text::MultilineValue>,
) -> Self {
Self {
destination: destination.into(),
title: Some(title.into()),
link_kind: LinkKind::Inline,
}
}
pub fn reference(
destination: impl Into<text::Value>,
value: impl Into<text::MultilineValue>,
reference_kind: LinkReferenceKind,
) -> Self {
Self {
destination: destination.into(),
title: None,
link_kind: LinkKind::Reference(LinkReference {
value: value.into(),
link_reference_kind: reference_kind,
}),
}
}
pub fn reference_with_title(
destination: impl Into<text::Value>,
value: impl Into<text::MultilineValue>,
reference_kind: LinkReferenceKind,
title: impl Into<text::MultilineValue>,
) -> Self {
Self {
destination: destination.into(),
title: Some(title.into()),
link_kind: LinkKind::Reference(LinkReference {
value: value.into(),
link_reference_kind: reference_kind,
}),
}
}
#[inline(always)]
pub fn destination(&self) -> &text::Value {
&self.destination
}
#[inline(always)]
pub fn destination_str<'a>(&'a self, source: &'a str) -> &'a str {
self.destination.str(source)
}
#[inline(always)]
pub fn title(&self) -> Option<&text::MultilineValue> {
self.title.as_ref()
}
#[inline(always)]
pub fn title_str<'a>(&'a self, source: &'a str) -> Option<Cow<'a, str>> {
self.title.as_ref().map(|t| t.str(source))
}
#[inline(always)]
pub fn link_kind(&self) -> &LinkKind {
&self.link_kind
}
}
impl NodeKind for Image {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Image"
}
}
impl PrettyPrint for Image {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(
w,
"{}Destination: {}",
pp_indent(level),
self.destination.str(source)
)?;
if let Some(title) = &self.title {
writeln!(w, "{}Title: {}", pp_indent(level), title.str(source))?;
}
Ok(())
}
}
impl From<Image> for KindData {
fn from(data: Image) -> Self {
KindData::Image(data)
}
}
#[derive(Debug)]
pub struct RawHtml {
value: text::MultilineValue,
}
impl RawHtml {
pub fn new(value: text::MultilineValue) -> Self {
Self { value }
}
#[inline(always)]
pub fn value(&self) -> &text::MultilineValue {
&self.value
}
pub fn str<'a>(&'a self, source: &'a str) -> Cow<'a, str> {
self.value.str(source)
}
pub fn bytes<'a>(&'a self, source: &'a str) -> Cow<'a, [u8]> {
self.value.bytes(source)
}
}
impl NodeKind for RawHtml {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"RawHtml"
}
}
impl PrettyPrint for RawHtml {
fn pretty_print(&self, w: &mut dyn Write, source: &str, level: usize) -> fmt::Result {
writeln!(w, "{}Value: {}", pp_indent(level), self.str(source))?;
Ok(())
}
}
impl From<RawHtml> for KindData {
fn from(data: RawHtml) -> Self {
KindData::RawHtml(data)
}
}
#[derive(Debug, Default)]
pub struct Strikethrough {}
impl Strikethrough {
pub fn new() -> Self {
Self {}
}
}
impl NodeKind for Strikethrough {
fn typ(&self) -> NodeType {
NodeType::Inline
}
fn kind_name(&self) -> &'static str {
"Strikethrough"
}
}
impl PrettyPrint for Strikethrough {
fn pretty_print(&self, _w: &mut dyn Write, _source: &str, _level: usize) -> fmt::Result {
Ok(())
}
}
impl From<Strikethrough> for KindData {
fn from(e: Strikethrough) -> Self {
KindData::Strikethrough(e)
}
}
pub trait ExtensionData: Debug + PrettyPrint + NodeKind + Any {
fn as_any(&self) -> &dyn Any;
}
impl<T: PrettyPrint + NodeKind + Debug + Any> ExtensionData for T {
fn as_any(&self) -> &dyn Any {
self
}
}