use std::fmt;
use std::sync::Arc;
use uuid::Uuid;
use yrs::block::Prelim;
use crate::{
iter::{TraversalOrder, TreeIter},
Result, Tree, TreeError,
};
#[derive(Clone, Debug, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub enum NodeId {
#[default]
Root,
Id(String),
}
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
NodeId::Root => write!(f, "<ROOT>"),
NodeId::Id(id) => write!(f, "{}", id),
}
}
}
impl PartialEq<&str> for NodeId {
fn eq(&self, other: &&str) -> bool {
match self {
NodeId::Root => *other == "<ROOT>",
NodeId::Id(id) => id == other,
}
}
}
impl From<&str> for NodeId {
fn from(id: &str) -> Self {
match id {
"<ROOT>" => NodeId::Root,
_ => NodeId::Id(id.to_string()),
}
}
}
impl From<&String> for NodeId {
fn from(id: &String) -> Self {
NodeId::from(id.as_str())
}
}
impl From<String> for NodeId {
fn from(id: String) -> Self {
NodeId::from(id.as_str())
}
}
pub trait NodeApi {
fn id(self: &Arc<Self>) -> &NodeId;
fn create_child(self: &Arc<Self>) -> Result<Arc<Node>>;
fn create_child_at(self: &Arc<Self>, index: usize) -> Result<Arc<Node>>;
fn create_child_with_id(self: &Arc<Self>, id: impl Into<NodeId>) -> Result<Arc<Node>>;
fn create_child_with_id_at(
self: &Arc<Self>,
id: impl Into<NodeId>,
index: usize,
) -> Result<Arc<Node>>;
fn move_to(self: &Arc<Self>, parent: &Node, index: Option<usize>) -> Result<()>;
fn move_before(self: &Arc<Self>, other: &Arc<Node>) -> Result<()>;
fn move_after(self: &Arc<Self>, other: &Arc<Node>) -> Result<()>;
fn parent(self: &Arc<Self>) -> Option<Arc<Node>>;
fn ancestors(self: &Arc<Self>) -> Vec<Arc<Node>>;
fn children(self: &Arc<Self>) -> Vec<Arc<Node>>;
fn descendants(self: &Arc<Self>, order: TraversalOrder) -> Vec<Arc<Node>>;
fn siblings(self: &Arc<Self>) -> Vec<Arc<Node>>;
fn traverse(self: &Arc<Self>, order: TraversalOrder) -> TreeIter;
fn depth(self: &Arc<Self>) -> usize;
fn delete(self: &Arc<Self>, strategy: DeleteStrategy) -> Result<()>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeleteStrategy {
Promote,
Cascade,
}
pub struct Node {
id: NodeId,
tree: Arc<Tree>,
}
impl Node {
pub(crate) fn new(id: NodeId, tree: Arc<Tree>) -> Arc<Self> {
Arc::new(Self { id, tree })
}
fn do_create_child(
self: &Arc<Self>,
id: impl Into<NodeId>,
index: Option<usize>,
) -> Result<Arc<Self>> {
let id = id.into();
if id == NodeId::Root {
return Err(
TreeError::InvalidId("<ROOT> cannot be used as a node ID".to_string()).into(),
);
}
self.tree.update_node(&id, &self.id, index)?;
Ok(Self::new(id, self.tree.clone()))
}
fn move_relative(self: &Arc<Self>, other: &Arc<Node>, offset: usize) -> Result<()> {
if other.id == self.id {
return Err(TreeError::Cycle(self.id.clone(), other.id.clone()).into());
}
if other.id == NodeId::Root {
return Err(TreeError::InvalidTarget(NodeId::Root).into());
}
let new_parent = other.parent().unwrap();
let siblings = other.siblings();
let cur_idx = siblings
.iter()
.position(|sibling| sibling.id == other.id)
.unwrap();
let new_index = cur_idx + offset;
self.tree
.update_node(&self.id, &new_parent.id, Some(new_index))?;
Ok(())
}
pub fn set<V: Prelim + Into<yrs::Any>>(&self, key: &str, value: V) -> Result<V::Return> {
self.tree.set_data(&self.id, key, value)
}
pub fn get(&self, key: &str) -> Result<Option<yrs::Out>> {
self.tree.get_data(&self.id, key)
}
pub fn get_as<V: serde::de::DeserializeOwned>(&self, key: &str) -> Result<V> {
self.tree.get_data_as(&self.id, key)
}
}
impl NodeApi for Node {
fn id(self: &Arc<Self>) -> &NodeId {
&self.id
}
fn create_child(self: &Arc<Self>) -> Result<Arc<Self>> {
let id = Uuid::now_v7().to_string();
self.create_child_with_id(id)
}
fn create_child_at(self: &Arc<Self>, index: usize) -> Result<Arc<Self>> {
let id = Uuid::now_v7().to_string();
self.do_create_child(id, Some(index))
}
fn create_child_with_id(self: &Arc<Self>, id: impl Into<NodeId>) -> Result<Arc<Self>> {
self.do_create_child(id, None)
}
fn create_child_with_id_at(
self: &Arc<Self>,
id: impl Into<NodeId>,
index: usize,
) -> Result<Arc<Self>> {
self.do_create_child(id, Some(index))
}
fn children(self: &Arc<Self>) -> Vec<Arc<Self>> {
self.tree
.get_children(&self.id)
.into_iter()
.map(|id| Node::new(id.clone(), self.tree.clone()))
.collect()
}
fn descendants(self: &Arc<Self>, order: TraversalOrder) -> Vec<Arc<Self>> {
self.traverse(order).skip(1).collect()
}
fn parent(self: &Arc<Self>) -> Option<Arc<Self>> {
self.tree
.get_parent(&self.id)
.map(|id| Node::new(id, self.tree.clone()))
}
fn ancestors(self: &Arc<Self>) -> Vec<Arc<Self>> {
let mut ancestors = vec![];
let mut current = self.parent();
while let Some(parent) = current {
ancestors.push(parent.clone());
current = parent.parent();
}
ancestors
}
fn siblings(self: &Arc<Self>) -> Vec<Arc<Self>> {
if let Some(parent) = self.parent() {
parent.children().clone()
} else {
vec![]
}
}
fn traverse(self: &Arc<Self>, order: TraversalOrder) -> TreeIter {
self.tree.traverse_starting_at(self.id(), order)
}
fn depth(self: &Arc<Self>) -> usize {
if self.id == NodeId::Root {
return 0;
}
let mut depth = 1;
let mut current = self.tree.get_parent(&self.id);
while let Some(parent_id) = current {
if parent_id == NodeId::Root {
break;
}
depth += 1;
current = self.tree.get_parent(&parent_id);
}
depth
}
fn move_to(self: &Arc<Self>, parent: &Node, index: Option<usize>) -> Result<()> {
self.tree.update_node(&self.id, &parent.id, index)
}
fn move_before(self: &Arc<Self>, other: &Arc<Node>) -> Result<()> {
self.move_relative(other, 0)
}
fn move_after(self: &Arc<Self>, other: &Arc<Node>) -> Result<()> {
self.move_relative(other, 1)
}
fn delete(self: &Arc<Self>, strategy: DeleteStrategy) -> Result<()> {
self.tree.delete_node(&self.id, strategy)
}
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Node({})", self.id)
}
}