use std::{collections::HashSet, hash::Hash};
pub trait Node<Id> {
fn id(&self) -> &Id;
fn parent(&self) -> Option<Id>;
fn parent_set(&mut self, id: Id);
fn parent_set_none(&mut self);
fn children(&self) -> Vec<Id>;
fn children_ref_mut(&mut self) -> &mut Vec<Id>;
}
pub trait FlowBase {
type Id: Default + Clone + Hash + Eq;
type Node: Default + Clone + Node<Self::Id>;
fn orphan(&self) -> Vec<Self::Id>;
fn contains_node(&self, obj: &Self::Id) -> bool {
self.node(obj).is_some()
}
fn node(&self, obj: &Self::Id) -> Option<&Self::Node>;
fn node_mut(&mut self, obj: &Self::Id) -> Option<&mut Self::Node>;
fn parent(&self, obj: &Self::Id) -> Option<Self::Id> {
self.node(obj).map_or(None,
|node| {
node.parent()
})
}
fn children(&self, obj: &Self::Id) -> Vec<Self::Id> {
self.node(obj).map_or(Vec::new(),
|node| {
node.children()
})
}
fn friends(&self, obj: &Self::Id) -> Vec<Self::Id> {
self.parent(obj).map_or(Vec::new(), |obj| {
self.children(&obj)
})
}
fn nth_friend(&self, obj: &Self::Id) -> Option<usize> {
self.friends(obj).into_iter()
.position(|id| &id == obj)
}
fn children_owned(&self, obj: &Self::Id) -> Vec<Self::Id> {
self.children(obj).into_iter().filter_map(|id| {
if self.parent(&id) == Some(obj.clone()) {
Some(id)
} else {
None
}
}).collect()
}
fn is_owned(&self, obj: &Self::Id, owner: &Self::Id) -> bool {
self.parent(obj).map_or(false, |id| &id == owner)
&& self.children(owner).contains(obj)
}
fn is_linked(&self, obj: &Self::Id, owner: &Self::Id) -> bool {
self.parent(obj).map_or(true, |id| &id != owner)
&& self.children(owner).contains(obj)
}
fn node_offspring_set(&self, obj: &Self::Id) -> HashSet<Self::Id> {
let mut visit_set = HashSet::new();
let mut final_set = HashSet::new();
visit_set.insert(obj.clone());
while !visit_set.is_empty() {
let mut wait_set = HashSet::new();
for obj in visit_set.iter() {
let children = self.node(&obj)
.map(|x| x.children() )
.unwrap_or_default();
wait_set.extend(children);
}
final_set.extend(wait_set.iter().cloned());
visit_set.clear();
visit_set.extend(wait_set);
}
final_set
}
fn node_ownership_set(&self, obj: &Self::Id) -> HashSet<Self::Id> {
let mut visit_set = HashSet::new();
let mut final_set = HashSet::new();
if self.contains_node(obj) {
visit_set.insert(obj.clone());
final_set.insert(obj.clone());
}
while !visit_set.is_empty() {
let mut wait_set = HashSet::new();
for obj in visit_set.iter() {
let children = self.node(&obj)
.map(|x| x.children())
.unwrap_or_default();
let set: Vec<Self::Id> = children.into_iter().filter_map(|id| {
self.node(&id).map(|node| {
if node.parent() == Some(obj.clone()) {
Some(id)
} else {
None
}
}).flatten()
}).collect();
wait_set.extend(set);
}
final_set.extend(wait_set.iter().cloned());
visit_set.clear();
visit_set.extend(wait_set);
}
final_set
}
}
pub trait FlowCheck {
fn check(&self) -> Result<(), (FlowError, String)>;
fn check_assert(&self) {
if cfg!(debug_assertions) {
if let Err((err, current)) = self.check() {
panic!("{:?}{}", err, current)
}
}
}
}
pub trait FlowMap: FlowBase + FlowCheck {
fn grow(&mut self, obj: Self::Node) -> Result<Self::Id, FlowError>;
fn erase(&mut self, obj: &Self::Id) -> Result<(), FlowError>;
}
pub trait FlowLink: FlowBase + FlowCheck {
fn link(&mut self, obj: &Self::Id, owner: &Self::Id, nth: usize) -> Result<(), FlowError> {
if ! self.contains_node(obj) {
Err(FlowError::NotExistObj)?
}
let res = self.node_mut(owner).map(|owner| {
if owner.children().contains(obj) {
return Ok(())
}
if nth > owner.children().len() {
Err(FlowError::InvalidLen)?
}
owner.children_ref_mut().insert(nth, obj.clone());
Ok(())
}).unwrap_or(Err(FlowError::NotExistOwner));
self.check_assert();
res
}
fn link_push(&mut self, obj: &Self::Id, owner: &Self::Id) -> Result<(), FlowError> {
let nth = self.node(owner).map_or(0, |node| node.children().len());
let res = self.link(obj, owner, nth);
self.check_assert();
res
}
fn detach(&mut self, obj: &Self::Id, owner: &Self::Id) -> Result<(), FlowError> {
if ! self.contains_node(obj) {
Err(FlowError::NotExistObj)?
}
let res = self.node_mut(owner).map(|owner| {
if ! owner.children().contains(obj) {
Err(FlowError::AbandonedChild)?
}
owner.children_ref_mut().retain(|x| x != obj);
Ok(())
}).unwrap_or(Err(FlowError::NotExistOwner));
self.check_assert();
res
}
}
pub trait FlowDevote: FlowBase + FlowLink + FlowCheck {
fn devote(&mut self, obj: &Self::Id, owner: &Self::Id, nth: usize) -> Result<(), FlowError> {
let res = self.link(obj, owner, nth).and_then(|_| {
self.node_mut(obj).map(|obj| {
obj.parent_set(owner.clone());
Ok(())
}).unwrap_or(Err(FlowError::NotExistObj))
});
self.check_assert();
res
}
fn devote_push(&mut self, obj: &Self::Id, owner: &Self::Id) -> Result<(), FlowError> {
let res = self.link_push(obj, owner).and_then(|_| {
self.node_mut(obj).map_or(
Err(FlowError::NotExistObj),
|obj| {
obj.parent_set(owner.clone());
Ok(())
}
)
});
self.check_assert();
res
}
fn decay(&mut self, obj: &Self::Id) -> Result<(), FlowError> {
let owner = self.node(obj)
.map(|x| {
x.parent()
});
if let Some(None) = owner {
return Ok(())
}
let owner = owner.flatten();
let res = self.node_mut(obj).map_or(
Err(FlowError::NotExistObj),
|obj| {
obj.parent_set_none();
Ok(())
}
).and_then(|_| {
owner.map_or(
Err(FlowError::NotExistOwner),
|owner| {
self.detach(obj, &owner)
}
)
});
self.check_assert();
res
}
fn devote_loyal(&mut self, obj: &Self::Id, owner: &Self::Id, nth: usize) -> Result<(), FlowError> {
self.decay(&obj)?;
self.devote(&obj, &owner, nth)
}
fn devote_loyal_push(&mut self, obj: &Self::Id, owner: &Self::Id) -> Result<(), FlowError> {
self.decay(&obj)?;
self.devote_push(&obj, &owner)
}
}
pub trait FlowDock: FlowDevote + FlowCheck + Sized {
fn dock_unordered(&mut self, owner: &Self::Id, flow: Self) -> Result<(), FlowError> {
self.dock(owner, flow.orphan(), flow)
}
fn dock(&mut self, owner: &Self::Id, vec: Vec<Self::Id>, flow: Self) -> Result<(), FlowError>;
fn undock_impl(&mut self, obj: &Self::Id, owned: bool) -> Result<(Self, Vec<Self::Id>), FlowError>;
fn undock(&mut self, obj: &Self::Id) -> Result<(Self, Vec<Self::Id>), FlowError> {
self.undock_impl(obj, false)
}
fn undock_owned(&mut self, obj: &Self::Id) -> Result<(Self, Vec<Self::Id>), FlowError> {
self.undock_impl(obj, true)
}
fn snap(&self, obj: &Self::Id) -> Result<(Self, Vec<Self::Id>), FlowError>;
fn snap_owned(&self, obj: &Self::Id) -> Result<(Self, Vec<Self::Id>), FlowError>;
}
#[derive(Debug, Copy, Clone)]
pub enum Direction {
Forward,
Backward,
Ascend,
Descend,
}
impl Direction {
fn shift(&self) -> isize {
use Direction::*;
match self {
Forward => 1,
Backward => -1,
_ => 0
}
}
fn walk(&self, nth: usize, len: usize) -> Result<usize,()> {
let pos = nth as isize + self.shift();
if pos < 0 {
Err(())
} else if (pos as usize) < len {
Ok(pos as usize)
} else {
Err(())
}
}
}
pub trait FlowShift: FlowBase + FlowDevote {
fn shuttle(&self, obj: &Self::Id, dir: Direction) -> Result<Self::Id, FlowError> {
use Direction::*;
match dir {
Forward | Backward => {
let friends = self.friends(obj);
let nth = if let Some(nth) = friends.iter()
.position(|id| {
id == obj
})
{ nth } else { Err(FlowError::AbandonedChild)? };
let len = friends.len();
let walk = dir.walk(nth, len)
.map_err(|_| FlowError::InvalidLen)?;
Ok(friends[walk].clone())
}
Ascend => {
let candidate = self.parent(obj);
let res = candidate
.map_or(obj.clone(), |id| {
id
});
Ok(res)
}
Descend => {
let candidate = self.children(obj).get(0).cloned();
let res = candidate
.map_or(obj.clone(), |id| {
id
});
Ok(res)
}
}
}
fn shuttle_iter(&self, obj: &Self::Id, dir: Direction) -> Result<Self::Id, FlowError> {
use Direction::*;
match dir {
Forward | Backward => {
self.shuttle(obj, dir).map_or_else(
|_| {
Ok(self.parent(obj).unwrap_or(obj.clone()))
},
|id| Ok(id)
)
}
Ascend | Descend => self.shuttle(obj, dir),
}
}
fn migrate(&mut self, obj: &Self::Id, dir: Direction) -> Result<(), FlowError> {
use Direction::*;
if ! self.contains_node(obj) { Err(FlowError::NotExistObj)? }
match dir {
Forward | Backward => {
let owner = self.parent(obj).ok_or(FlowError::NotExistObj)?;
let nth = self.nth_friend(obj).ok_or(FlowError::AbandonedChild)?;
let len = self.friends(&owner).len();
let walk = dir.walk(nth, len)
.map_err(|_| FlowError::InvalidLen)?;
self.decay(obj)?;
self.devote(obj, &owner, walk)?
}
Ascend => {
let parent = self.parent(obj).ok_or(FlowError::NotExistObj)?;
let owner = self.parent(&parent).ok_or(FlowError::IsOrphaned)?;
let nth = self.nth_friend(&parent).ok_or(FlowError::AbandonedChild)? + 1;
self.decay(obj)?;
self.devote(obj, &owner, nth)?
}
Descend => { Err(FlowError::InvalidDir)? }
}
self.check_assert();
Ok(())
}
fn migrate_iter(&mut self, obj: &Self::Id, dir: Direction) -> Result<(), FlowError> {
use Direction::*;
match dir {
Forward | Backward => {
self.migrate(obj, dir).map_or_else(
|e| {
if let FlowError::InvalidLen = e {
self.migrate(obj, Ascend)
} else { Err(e) }
},
|v| Ok(v)
)
}
Ascend | Descend => self.migrate(obj, dir)
}
}
}
#[derive(Debug)]
pub enum FlowError {
NotExistObj,
NotExistOwner,
InvalidLen,
ExistGrow,
ExistDock,
OwnerDetach,
LinkedUndock,
InvalidDir,
NotOrphaned,
IsOrphaned,
NodeIdNotMatch,
NotExistParent,
NotExistChild,
AbandonedChild,
}
pub trait Flow: FlowBase + FlowCheck + FlowMap + FlowLink + FlowDevote + FlowDock + FlowShift {}