use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::page::Link;
#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Document {
pub nodes: Vec<Raw>,
}
impl std::fmt::Debug for Document {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "nodes: {}", self.nodes.len())
}
}
impl Document {
pub fn nth(&self, n: usize) -> Option<Node<'_>> {
Node::new(self, n)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
#[repr(usize)]
pub enum HeaderKind {
Main = 1,
Sub = 2,
Section = 3,
Subsection = 4,
Minor = 5,
Detail = 6,
}
#[derive(Default, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum Data {
Section {
id: usize,
},
Header {
id: String,
kind: HeaderKind,
},
Text {
contents: String,
},
Division,
Paragraph,
Span,
Reflink,
Hatnote,
RedirectMessage,
Disambiguation,
Blockquote,
OrderedList,
UnorderedList,
ListItem,
DescriptionList,
DescriptionListTerm,
DerscriptionListDescription,
Bold,
Italic,
Linebreak,
Link(Link),
#[default]
Unknown,
Unsupported(UnsupportedElement),
UnsupportedInline(UnsupportedElement),
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum UnsupportedElement {
Table,
Image,
Figure,
MathElement,
PreformattedText,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Raw {
pub index: usize,
pub parent: Option<usize>,
pub prev: Option<usize>,
pub next: Option<usize>,
pub first_child: Option<usize>,
pub last_child: Option<usize>,
pub data: Data,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Node<'a> {
document: &'a Document,
index: usize,
}
impl<'a> Node<'a> {
pub fn new(document: &'a Document, index: usize) -> Option<Node<'a>> {
if index < document.nodes.len() {
Some(Node { document, index })
} else {
None
}
}
pub fn index(&self) -> usize {
self.index
}
pub fn raw(&self) -> &'a Raw {
&self.document.nodes[self.index]
}
pub fn data(&self) -> &'a Data {
&self.raw().data
}
pub fn parent(&self) -> Option<Node<'a>> {
self.raw()
.parent
.map(|index| self.document.nth(index).unwrap())
}
pub fn prev(&self) -> Option<Node<'a>> {
self.raw()
.prev
.map(|index| self.document.nth(index).unwrap())
}
pub fn next(&self) -> Option<Node<'a>> {
self.raw()
.next
.map(|index| self.document.nth(index).unwrap())
}
pub fn first_child(&self) -> Option<Node<'a>> {
self.raw()
.first_child
.map(|index| self.document.nth(index).unwrap())
}
pub fn last_child(&self) -> Option<Node<'a>> {
self.raw()
.last_child
.map(|index| self.document.nth(index).unwrap())
}
pub fn descendants(&self) -> Descendants<'a> {
Descendants {
start: *self,
current: *self,
done: false,
}
}
pub fn children(&self) -> Children<'a> {
Children {
next: self.first_child(),
}
}
}
#[derive(Clone, Debug)]
pub struct Descendants<'a> {
start: Node<'a>,
current: Node<'a>,
done: bool,
}
impl<'a> Iterator for Descendants<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Node<'a>> {
if self.done {
return None;
}
if self.start.index() == self.current.index() {
if let Some(first_child) = self.current.first_child() {
self.current = first_child;
} else {
self.done = true;
return None;
}
} else {
if let Some(first_child) = self.current.first_child() {
self.current = first_child;
} else if let Some(next) = self.current.next() {
self.current = next;
} else {
loop {
let parent = self.current.parent().unwrap();
if parent.index() == self.start.index() {
self.done = true;
return None;
}
if let Some(next) = parent.next() {
self.current = next;
break;
}
self.current = parent;
}
}
}
Some(self.current)
}
}
pub struct Children<'a> {
next: Option<Node<'a>>,
}
impl<'a> Iterator for Children<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Node<'a>> {
if let Some(next) = self.next {
self.next = next.next();
Some(next)
} else {
None
}
}
}