use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct Group {
name: String,
enabled: bool,
show_child_details: bool,
child_structures: HashSet<String>,
child_groups: HashSet<String>,
parent_group: Option<String>,
}
impl Group {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
enabled: true,
show_child_details: true,
child_structures: HashSet::new(),
child_groups: HashSet::new(),
parent_group: None,
}
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
#[must_use]
pub fn show_child_details(&self) -> bool {
self.show_child_details
}
pub fn set_show_child_details(&mut self, show: bool) {
self.show_child_details = show;
}
#[must_use]
pub fn parent_group(&self) -> Option<&str> {
self.parent_group.as_deref()
}
pub fn set_parent_group(&mut self, parent: Option<String>) {
self.parent_group = parent;
}
pub fn add_structure(&mut self, type_name: &str, name: &str) {
self.child_structures.insert(format!("{type_name}:{name}"));
}
pub fn remove_structure(&mut self, type_name: &str, name: &str) {
self.child_structures.remove(&format!("{type_name}:{name}"));
}
#[must_use]
pub fn contains_structure(&self, type_name: &str, name: &str) -> bool {
self.child_structures
.contains(&format!("{type_name}:{name}"))
}
pub fn add_child_group(&mut self, group_name: &str) {
self.child_groups.insert(group_name.to_string());
}
pub fn remove_child_group(&mut self, group_name: &str) {
self.child_groups.remove(group_name);
}
#[must_use]
pub fn contains_child_group(&self, group_name: &str) -> bool {
self.child_groups.contains(group_name)
}
pub fn child_structures(&self) -> impl Iterator<Item = (&str, &str)> {
self.child_structures.iter().filter_map(|s| {
let parts: Vec<&str> = s.splitn(2, ':').collect();
if parts.len() == 2 {
Some((parts[0], parts[1]))
} else {
None
}
})
}
pub fn child_groups(&self) -> impl Iterator<Item = &str> {
self.child_groups.iter().map(std::string::String::as_str)
}
#[must_use]
pub fn num_child_structures(&self) -> usize {
self.child_structures.len()
}
#[must_use]
pub fn num_child_groups(&self) -> usize {
self.child_groups.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.child_structures.is_empty() && self.child_groups.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_group_creation() {
let group = Group::new("test_group");
assert_eq!(group.name(), "test_group");
assert!(group.is_enabled());
assert!(group.is_empty());
}
#[test]
fn test_add_structure() {
let mut group = Group::new("test");
group.add_structure("PointCloud", "my_points");
assert!(group.contains_structure("PointCloud", "my_points"));
assert!(!group.is_empty());
assert_eq!(group.num_child_structures(), 1);
}
#[test]
fn test_remove_structure() {
let mut group = Group::new("test");
group.add_structure("PointCloud", "my_points");
group.remove_structure("PointCloud", "my_points");
assert!(!group.contains_structure("PointCloud", "my_points"));
assert!(group.is_empty());
}
#[test]
fn test_group_hierarchy() {
let mut parent = Group::new("parent");
parent.add_child_group("child");
assert!(parent.contains_child_group("child"));
assert_eq!(parent.num_child_groups(), 1);
let mut child = Group::new("child");
assert!(child.parent_group().is_none());
child.set_parent_group(Some("parent".to_string()));
assert_eq!(child.parent_group(), Some("parent"));
}
}