24 个版本
0.0.25 | 2024年6月24日 |
---|---|
0.0.24 | 2024年6月23日 |
0.0.22 | 2024年5月29日 |
0.0.21 | 2024年3月20日 |
0.0.14 | 2023年3月20日 |
284 每月下载量
31 每月下载次数
用于 toolproof
245KB
4K SLoC
非破坏性
非破坏性编辑尝试尽可能多地保留现有结构,同时允许在原地修改文档。
该项目目前尚未完成!
有关如何使用 YAML 支持的详细信息,请参阅相应的模块
与文档一起工作
文档被反序列化为一个大型对象,其中所有访问和修改都必须发生。这使得 API 比典型的序列化库更难使用,但这是确保可以访问所有必要数据进行非破坏性编辑所必需的。
一个特殊的问题是,每个提供对文档可变访问的方法都需要有两个变体: as_<something>_mut
和 into_<something>_mut
。如果我们查看 ValueMut::as_mapping_mut
和 ValueMut::into_mapping_mut
的差异,后者消耗 self
并返回一个与其相关联的生命周期的 ValueMut
。
use anyhow::Context;
use nondestructive::yaml;
let mut doc = yaml::from_slice(
r"
greeting: Hello World!
"
)?;
// Access through the document:
assert_eq!(
doc.as_ref().as_mapping().and_then(|m| m.get("greeting")?.as_str()),
Some("Hello World!")
);
// Mutation through the document:
let mut mapping = doc.as_mut().into_mapping_mut().context("missing root mapping")?;
mapping.insert_str("greeting2", "Hello Rust!");
assert_eq!(
doc.to_string(),
r"
greeting: Hello World!
greeting2: Hello Rust!
"
);
如果我们更改使用 into_mapping_mut
的行,我们将获得一个生命周期错误
error[E0716]: temporary value dropped while borrowed
--> src\lib.rs:43:19
|
20 | let mut mapping = doc.as_mut().as_mapping_mut().context("missing root mapping")?;
| ^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary value which is freed while still in use
21 | mapping.insert_str("greeting2", "Hello Rust!");
| ---------------------------------------------- borrow later used here
|
help: consider using a `let` binding to create a longer lived value
|
20 + let binding = doc.as_mut();
21 ~ let mut mapping = binding.as_mapping_mut().context("missing root mapping")?;
|
我们可以按照建议将其分配给局部变量,但是如果我们使用类似 Option::and_then
的组合器,则不可能做到这一点。
与文档一起工作的另一个重要方面是我们可以通过 标识符 全局 地处理值。这使得在应用它们之前存储所需的修改变得更容易。
use anyhow::Context;
use nondestructive::yaml;
let mut doc = yaml::from_slice(
r"
- 10
- 24
- 30
"
)?;
let mut edits = Vec::new();
// Build a collection of edits:
for value in doc.as_ref().as_sequence().context("missing sequence")? {
let Some(n) = value.as_u32() else {
continue;
};
if n % 10 == 0 {
edits.push((value.id(), n / 10));
}
}
// Apply stored edits:
for (id, new_number) in edits {
doc.value_mut(id).set_u32(new_number);
}
assert_eq!(
doc.to_string(),
r"
- 1
- 24
- 3
"
);
示例
这提供了对可用 API 的更广泛视图,以及访问器和修改器之间的差异。
use anyhow::Context;
use nondestructive::yaml;
let mut doc = yaml::from_slice(
r"
name: Descartes
country: Grece
"
)?;
let mapping = doc.as_ref().as_mapping().context("missing mapping")?;
let name = mapping.get("name").context("missing name")?;
assert_eq!(name.as_str(), Some("Descartes"));
let mut mapping = doc.as_mut().into_mapping_mut().context("missing mapping")?;
let mut name = mapping.get_mut("name").context("missing name")?;
name.set_string("Plato");
let mut country = mapping.get_mut("country").context("missing country")?;
country.set_string("Greece");
assert_eq!(
doc.to_string(),
r"
name: Plato
country: Greece
"
);
依赖关系
~1.5MB
~25K ~25K SLoC