use std::any::Any;
use std::fmt::Debug;
pub trait Node: Debug + Any {
fn clone_node(&self) -> Box<dyn Node>;
fn node_ptr(&self) -> usize;
fn gi(&self) -> Option<String>;
fn id(&self) -> Option<String>;
fn data(&self) -> Option<String>;
fn children(&self) -> Box<dyn NodeList>;
fn all_children(&self) -> Box<dyn NodeList>;
fn parent(&self) -> Option<Box<dyn Node>>;
fn attribute_string(&self, name: &str) -> Option<String>;
fn is_element(&self) -> bool;
fn is_text(&self) -> bool;
fn node_eq(&self, other: &dyn Node) -> bool;
fn node_id(&self) -> usize;
}
pub trait NodeList: Debug {
fn is_empty(&self) -> bool;
fn first(&self) -> Option<Box<dyn Node>>;
fn rest(&self) -> Box<dyn NodeList>;
fn length(&self) -> usize;
fn get(&self, index: usize) -> Option<Box<dyn Node>>;
}
pub trait Grove: Debug {
fn root(&self) -> Box<dyn Node>;
fn element_with_id(&self, id: &str) -> Option<Box<dyn Node>>;
}
#[derive(Debug, Clone)]
pub struct EmptyNodeList;
impl EmptyNodeList {
pub fn new() -> Self {
EmptyNodeList
}
}
impl Default for EmptyNodeList {
fn default() -> Self {
Self::new()
}
}
impl NodeList for EmptyNodeList {
fn is_empty(&self) -> bool {
true
}
fn first(&self) -> Option<Box<dyn Node>> {
None
}
fn rest(&self) -> Box<dyn NodeList> {
Box::new(EmptyNodeList::new())
}
fn length(&self) -> usize {
0
}
fn get(&self, _index: usize) -> Option<Box<dyn Node>> {
None
}
}
#[derive(Debug)]
pub struct VecNodeList {
nodes: std::rc::Rc<Vec<Box<dyn Node>>>,
offset: usize,
}
impl VecNodeList {
pub fn new(nodes: Vec<Box<dyn Node>>) -> Self {
VecNodeList {
nodes: std::rc::Rc::new(nodes),
offset: 0,
}
}
fn from_rc(nodes: std::rc::Rc<Vec<Box<dyn Node>>>, offset: usize) -> Self {
VecNodeList { nodes, offset }
}
}
impl NodeList for VecNodeList {
fn is_empty(&self) -> bool {
self.offset >= self.nodes.len()
}
fn first(&self) -> Option<Box<dyn Node>> {
self.nodes.get(self.offset).map(|n| n.clone_node())
}
fn rest(&self) -> Box<dyn NodeList> {
if self.offset + 1 >= self.nodes.len() {
Box::new(EmptyNodeList::new())
} else {
Box::new(VecNodeList::from_rc(self.nodes.clone(), self.offset + 1))
}
}
fn length(&self) -> usize {
self.nodes.len().saturating_sub(self.offset)
}
fn get(&self, index: usize) -> Option<Box<dyn Node>> {
self.nodes.get(self.offset + index).map(|n| n.clone_node())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_traits_defined() {
}
#[test]
fn test_empty_node_list() {
let empty = EmptyNodeList::new();
assert!(empty.is_empty());
assert_eq!(empty.length(), 0);
assert!(empty.first().is_none());
assert!(empty.get(0).is_none());
assert!(empty.rest().is_empty());
}
}