4 个版本

0.1.3 2023 年 9 月 9 日
0.1.2 2023 年 9 月 7 日
0.1.1 2023 年 9 月 7 日
0.1.0 2023 年 9 月 7 日

#1093 in 数据结构

每月 30 次下载

GPL-3.0 许可证

58KB
1K SLoC

hedel-rs

License Latest Version Documentation

分层双向链表

hedel-rs 提供了您在 Rust 中创建自己的分层双向链表抽象所需的一切,适合 DOM 树。当您需要嵌套的节点生成时,它是一个合适的选择。(例如,使用宏 node!(1, node!(2)))它基于 RcWeak 以及对 UnsafeCellHedelCell)的安全封装。

如果您对链表不熟悉,可以考虑阅读 用大量链表学习 Rust

理念

Hedel 并不完全是一个树结构。

  • NodeList 是对其第一个节点的一个包装。没有根节点。这允许根级别的兄弟节点。 NodeList 还会解引用到其第一个节点,让您可以调用 Node 的方法。
  • Node 是对其内容的指针以及允许导航的其他指针。这些指针是:parentchildprevnext,其中 child 是指向其第一个子节点的指针。
  • 支持使用宏进行节点生成:您可以使用 node!(1) 并嵌套您想要的任意数量的节点。

特性

  • HedelCell:一个依赖于 UnsafeCell 的安全单元格结构,类似于 RefCell 但体积更小。

  • Node/WeakNode:为了避免内存泄漏,我们还提供了 Node 的弱版本。

  • 宏:使用 node!() 和 list!() 快速生成节点。

    let node = node!(45);
    let my_node = node!("Parent",
      node!("Child"),
      node!("Child")
    );
    
    let my_list = list!(
      node!(2),
      node!(3)
    );
    
  • 识别和比较:创建自己的标识符实现 CompareNode 特性。

    pub enum NumIdent {
          Equal(i32),
          BiggerThan(i32),
          SmallerThan(i32)
    }
    
    impl CompareNode<i32> for NumIdent {
        fn compare(&self, node: &Node<i32>) -> bool {
            match &self {
              Equal(n) => {
                    as_content!(node, |content| {
                      return content == &n;
                    });
                },
              BiggerThan(n) => {
                as_content!(node, |content| {
                  return content > &n;
                });
              },
              SmallerThan(n) => {
                as_content!(node, |content| {
                    return content < &n;
                });
              }
          }
      }
    }
    
    fn main() {
      let node = node!(3);
      assert!(NumIdent::BiggerThan(2).compare(&node));
    }  
    
  • 收集:遍历链表并收集匹配标识符的节点。

    let node = node!(1,
      node!(2),
      node!(3),
      node!(4),
      node!(5)
    );
    
    let collection = node.collect_children(&NumIdent::BiggerThan(3));
    
    for node in collection.into_iter() {
      println!("{}" node.to_content());
    }
    
  • 分离:从链表中分离匹配标识符的节点。

    let node = node!(1
      node!(2),
      node!(3),
      node!(4),
      node!(5)
    );
    
    let three = node.find_child(&NumIdent::Equal(3)).unwrap();
    three.detach();
    
    assert_eq!(node.find_child(&NumIdent::Equal(3)), None);
    
  • 插入或追加:在链表的任何位置插入节点。

    let node = node!(1,
      node!(3),
      node!(4),
      node!(5)
    );
    
    node.insert_child(0, node!(2));
    
    assert_eq!(node.child().unwrap().to_content(), 2);
    
    node.append_child(node!(6));
    
    assert_eq!(node.get_last_child().unwrap().to_content(), 6);
    

依赖项

~300–760KB
~18K SLoC