5个版本

0.0.5 2023年10月13日
0.0.4 2023年9月9日
0.0.3 2021年5月4日
0.0.2 2021年3月26日
0.0.1 2021年3月25日

#580 in 数据结构

每月 29 次下载

MIT 许可证

270KB
7.5K SLoC

🎯 hit

Build Status codecov

hit 是一个Rust库,用于处理以树状文档结构化的数据,具有以下特性

  • H分层
  • I索引
  • T类型

这个库旨在管理内存中的深度嵌套文档,使用严格类型的数据结构和多个内部链接。这可以表示文字处理文档、目录及其文件和子文件夹以及符号链接...

分层

每个文档都像MongoDB文档一样以文档树的形式组织。这意味着文档总是以一个根 object 开始。在 hit 中,object 被定义为键/值列表。

值可以是

  • 简单的(字符串、数字、日期)
  • 或者它们可以包含 其他子对象。每个子对象(除了根对象)都可以作为一个 对象属性 来定位。
  • 它们也可以包含对其他对象的 引用

(TODO: 链接到属性类型)

索引

每个 object 都是索引的。这意味着

  • 每个对象都必须有一个 _id,其值为Rust String
  • 每个对象(除了根对象)都可以使用这三个索引来定位
    • parent_id
    • parent_property
    • parent_position

索引允许 hit 提供(TODO: 链接到方法)referencereference_array 类型字段。它们灵感来自关系数据库中的外键,hit 强制一致性规则:只要文档中还有对该对象的引用,就不能删除该对象。

索引还允许您轻松地找到对对象的引用。(TODO: 链接到方法)

类型化

文档中的每个 object 必须有一个(待完善:链接)Model。模型通过字符串 id 来标识,并在 objecttype 属性中引用。为了从 ids 解析模型定义,每个 hit 实例都必须初始化一个包含定义的(待完善:链接)Kernel

模型

  • 列出对象的接受字段名称
  • 使用 field types(待完善:链接)限制接受的值,以及可选的 validators(待完善:链接)

开始使用

hit 是一个 Rust 库。您可以通过将以下行添加到您的 Cargo.toml 文件中来将其添加到您的项目中

TODO

指南:如何创建和使用 hit 实例

创建 hit 实例

要创建一个 hit 数据实例,您需要一个包含模型定义的(待完善:链接)Kernel。一个核心内核,由我官方支持,是递归设计的(待完善:链接)hit_model,它允许您为 hit 模型化模型。

为了使其更简单,让我们从基本的、虽然完全无用的(待完善:链接)hit_test_file_model 开始,它表示带链接的目录/文件结构。

我们将使用(待完善:链接)Hit::new_with_values 来创建模型。如果您没有初始值,您也可以使用(待完善:链接)Hit::new 函数。

use hit_file_model::create_kernel;
use hit::{ Hit, ObjectValue, IndexEntryProperty };
use std::collections::HashMap;

// create the kernel
let kernel = create_kernel();

// create a string id for the object
let id = "my_id".into();

// initiate the name value for our root object
let mut values = HashMap::new();
values.insert("name".into(), ObjectValue::String("name".into()));

// we can now create the hit instance
let hit_instance = Hit::new_with_values(
  id,
  kernel,
  values,
  // you must specify the main model name
  "file/filesystem"
);

属性类型

hit 允许以下属性类型作为值。该(待完善:链接)ObjectValue 枚举处理此类型系统。

简单值

这些值使用(待完善:链接)Hit::set 值设置。

  • 字符串

    一个 string 字段接受 Rust String 值。

  • 数字

    一个 number 字段接受 Rust f32 值。

  • 布尔值

  • 日期

    一个 date 字段接受作为 Rust i64 值的时间戳。

复杂值

这些字段只能使用 Hit 结构体中的特定方法进行填充。

  • 子对象

    一个 sub_object 字段接受一个 hit 对象作为值。该字段将是填充它的对象的唯一父对象。

  • 子对象数组

    一个 sub_object_array 字段接受多个 hit 对象作为值。它也将是填充它的对象的唯一可能父对象。

  • 引用

    一个 reference 字段接受同一根 Hit 实例中的另一个对象的引用。它不能设置为无效 ID,同样,如果存在对该对象的引用,则不能从根实例中删除对象。请参阅(待完善:链接)强制验证

  • 引用数组

    同样,一个 reference_array 字段接受多个引用。

以下子章节将解释如何使用这些值类型。示例将使用先前创建的 hit_test_file_model 实例。

设置简单/标量值

您可以使用(待补充:链接)Hit::set方法设置一个简单值。

示例

hit_instance::set(
  "my_id".into(),
  "name".into(),
  ObjectValue::String("my_instance_name".into())
).expect("This should set the root object name");

操作可能会返回错误

  • (待补充:链接):HitError::IDNotFound 如果模型ID不存在
  • (待补充:链接):HitError::PropertyNotFound 如果模型没有指定的属性
  • (待补充:链接):HitError::InvalidDataType 如果模型属性不接受该值

添加对象

您可以使用Hit::insert方法将子对象添加到现有object。您需要提供

  • 对象的model_type,这是内核知道它的ID。
  • 新插入对象的String ID。
  • 您可以在Hashmap<String, ObjectValue>中为对象的某些字段提供值
  • 对象必须始终有一个父对象:您必须提供一个ID和属性名来插入它
  • 您可以通过指定将被插入的对象的ID来在属性的具体位置插入对象。如果不提供ID(在函数调用中使用None),则对象将被插入列表的末尾。

示例

hit_instance::insert(
  "file/folder".into(),
  "id2".into(),
  Hashmap::new(),
  IndexEntryProperty {
    id: "my_id".into(),
    property: "folders".into(),
  },
  None,
).expect("Insertion has failed");

删除对象

引用对象

删除对象引用

指南:验证

hit为您的数据提供验证。有两种验证级别

强制验证

有一些基本的数据完整性规则,hit模型将不允许您违反这些规则。当您设置值或执行操作时,如果您的操作违反了这些规则,则操作将返回错误。hit旨在具有最小数量的这些错误。这些错误包括

  • 引用完整性。如果您尝试引用不存在的对象ID,或删除在其他字段中被引用的对象,则您的操作将不会执行。
  • 数据类型。如果您将字段设置为不接受其FieldTypeObjectValue,则您的操作将被拒绝。
  • 对象模型名称。如果您尝试插入具有无效模型名称的对象,则您的操作将被拒绝。
  • 对象字段名称。如果您尝试设置对象模型上不存在的属性,或创建具有无效属性名称的对象。

(待补充): 能够向模型添加强制验证。

非阻塞验证

主要的验证模型是非阻塞:这意味着您可以为对象的属性分配无效值。

持久化hit数据

JSON导入/导出

HitImporter/Exporter:创建自己的序列化/反序列化器

插件/事件处理器

待补充:编写本章内容

指南:创建模型

hit依赖于模型。类似于SQL表定义,模型Model结构的实例。一个Hit实例依赖于一个Kernel,它是一组模型(以及稍后我们将看到的插件)。由于Hit实例具有分层、树状结构,它必须有一个根对象,该对象与其所有子对象一样,都由一个Model结构来组织。

在我们的(TODO:链接到GitHub)hit_test_file_model示例中,file/filesystem模型是根对象,包含文件和文件夹子对象。

在该指南部分,我们将介绍如何创建自己的内核、模型以及插件。

模型定义

model具有以下属性

  • 名称

  • 定义 这是一个键/值字典。定义是一个实现ModelField特质的struct。您可以编写自己的模型字段,但hit提供了标准字段,这些字段与上一章中定义的类型非常明显地匹配

    • (TODO:链接)字符串
    • (TODO:链接)整数
    • (TODO:链接)浮点数
    • (TODO:链接)日期
    • (TODO:链接)子对象
    • (TODO:链接)子对象数组
    • (TODO:链接)引用
    • (TODO:链接)引用数组

模型宏

验证器

字段验证器

对象验证器

标准库

创建自定义字段类型

内核

内核宏

TODO:创建宏^^

TODO:稳定化

  • 编写指南
  • 编写Rust文档
  • 测试字段结构?
  • 引用数组的验证
  • 测试删除包含其他对象的对象

TODO:稳定化后

  • 明确API
  • 字符串类型依赖的枚举=>
  • 提供方法,以便您不需要使用LinkedHashMap来使用hit

TODO:较低优先级

  • 使用Rust枚举进行修改
  • 重构带有allows_model的move函数
  • 实现ACID事务?
  • 在Hit中集成model_type索引
  • 使用强类型但可扩展的错误进行验证?如何做到这一点?

依赖

~3–4.5MB
~80K SLoC