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 在 算法
55KB
1K SLoC
快速将反序列化数据转换为图
快速入门
提供核心特质 Identity
, Identifiable
, Query
和 Edges
作为遍历任意数据和将其链接成图的抽象。允许通过相同数据执行泛型遍历/多种类型的遍历。
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