5个版本

0.2.1 2022年7月13日
0.2.0 2022年7月13日
0.1.2 2022年7月7日
0.1.1 2022年7月7日
0.1.0 2022年7月6日

#1368算法


3 个crate使用 (2直接使用)

Apache-2.0

55KB
1K SLoC

快速将反序列化数据转换为图

快速入门

提供核心特质 Identity, Identifiable, QueryEdges 作为遍历任意数据和将其链接成图的抽象。允许通过相同数据执行泛型遍历/多种类型的遍历。

ExtractData 特质和节点注解允许将元数据提取到图中。

单线程(尽管速度仍然很快)。

完整示例

use meshed::prelude::*;
use std::fmt;
type Id = i32;

struct Item {
    id: Id,
    children: Vec<Id>
}

struct ListOfItems {
    items: Vec<Item>
}

// Core traits 
use meshed::identify::{Identity, Identifiable};

// For convenience this is also implemented by default for i32.
// Ids must be lightweight, comparable and cheaply cloneable. 
// if you're using strings, consider using an Rc

impl Label for Item {
    type Label = Id;
    fn label(&self) -> Self::Label {
        self.id
    }
}

impl Edges<Id, ()> for Item {
    fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<Id, ()>> {
        let next_index = previous_edge_index.map(|i| i + 1).unwrap_or_default();
        let edge = self.children.get(next_index)?.clone();
        Some(Edge::new(self.get_id(), edge, next_index, ()))
    }
}

impl Identifiable<Id> for Item {
    fn get_id(&self) -> Id {
        self.id
    }
}
// This trait tells the graph system that a type can be used to 
// look up nodes when required
impl Query<Id, Item> for ListOfItems {
    fn query(&self, identifier: &Id) -> Option<&Item> {
        self.items.iter().find(|item| &item.id == identifier)
    }
    
    fn all(&self) -> Vec<&Item> {
        self.items.iter().collect()
    }
}

use meshed::graph::{Graph, SimpleGraphDefinition, GraphDefinition};
// Identifier, Node Metadata, Edge Metadata
type ItemGraph = Graph<SimpleGraphDefinition>;

let data = ListOfItems {
    items: vec![
        Item { id: 0, children: vec![1, 2] },
        Item { id: 1, children: vec![0, 3] },
        Item { id: 2, children: vec![3] },
        Item { id: 3, children: vec![1] }
    ]
};

let graph = SimpleGraphDefinition::build_graph(&data);

添加节点元数据

ExtractData 特质提供了一种从数据源中提取数据并将其添加到节点中的方法。

use std::borrow::Cow;
use meshed::prelude::*;
struct Item<'a> {
    id: i32,
    children: Vec<i32>,
    borrowed_value: Cow<'a, str>
}

struct Meta {
    value: String,
}

impl<'a> ExtractData<Meta> for Item<'a> {
    fn extract_data(&self) -> Meta {
        Meta { value: self.borrowed_value.to_string() }
    }
}

提取的值必须是 'static。这是为了防止图从源数据中拥有活动引用。源数据在图构建后可以被丢弃。

提供多种遍历

可以使用单元类型作为 Edges 的第二个参数提供多个边遍历。

use meshed::prelude::*;
struct Item {
    id: i32,
    children: Vec<i32>,
    parents: Vec<i32>,
}

struct Child;
struct Parent;

impl Edges<i32, Parent> for Item {
    fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<i32, Parent>> {
        let next_index = previous_edge_index.map(|i| i + 1).unwrap_or_default();
        let edge = self.parents.get(next_index)?.clone();
        Some(Edge::new(self.id, edge, next_index, Parent))
    }
}

impl Edges<i32, Child> for Item {
    fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<i32, Child>> {
        let next_index = previous_edge_index.map(|i| i + 1).unwrap_or_default();
        let edge = self.children.get(next_index)?.clone();
        Some(Edge::new(self.id, edge, next_index, Child))
    }
}

这允许在构建图时定义多个遍历

type ItemChildGraph = Graph<Id, (), Child>;
type ItemParentGraph = Graph<Id, (), Parent>;

遍历图

通过 EdgeTraversal 提供BFS和DFS遍历。非循环版本与 AcyclicTraversal 在同一模块中。

遍历生成 TraversedNodes 并可用于修剪或截断现有图。

标注节点

有时在遍历过程中,我们想要使用临时数据标注节点。这些标注在截断或修剪图时会被保留,但可能不会出现在所有节点中(或在不同遍历间保持一致)。

标注webpack块到webpack模块是一个很好的例子。模块所在的块高度依赖于遍历开始时的入口点。

let node = Node::new_default();

struct AnyStruct { value: usize }
enum EnumAnnotation {
  Variant
};

node.annotate(AnyStruct {  value: 3 });
node.annotate(EnumAnnotation::Variant);

这依赖于 Any 以及内部的向下转型。任何类型都可以存储在这里,只要该类型的副本只有一个。

依赖关系

~475KB