summaryrefslogtreecommitdiffstats
path: root/vendor/mdbook/src/utils/toml_ext.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/mdbook/src/utils/toml_ext.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/mdbook/src/utils/toml_ext.rs')
-rw-r--r--vendor/mdbook/src/utils/toml_ext.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/vendor/mdbook/src/utils/toml_ext.rs b/vendor/mdbook/src/utils/toml_ext.rs
new file mode 100644
index 000000000..bf25ad11b
--- /dev/null
+++ b/vendor/mdbook/src/utils/toml_ext.rs
@@ -0,0 +1,130 @@
+use toml::value::{Table, Value};
+
+pub(crate) trait TomlExt {
+ fn read(&self, key: &str) -> Option<&Value>;
+ fn read_mut(&mut self, key: &str) -> Option<&mut Value>;
+ fn insert(&mut self, key: &str, value: Value);
+ fn delete(&mut self, key: &str) -> Option<Value>;
+}
+
+impl TomlExt for Value {
+ fn read(&self, key: &str) -> Option<&Value> {
+ if let Some((head, tail)) = split(key) {
+ self.get(head)?.read(tail)
+ } else {
+ self.get(key)
+ }
+ }
+
+ fn read_mut(&mut self, key: &str) -> Option<&mut Value> {
+ if let Some((head, tail)) = split(key) {
+ self.get_mut(head)?.read_mut(tail)
+ } else {
+ self.get_mut(key)
+ }
+ }
+
+ fn insert(&mut self, key: &str, value: Value) {
+ if !self.is_table() {
+ *self = Value::Table(Table::new());
+ }
+
+ let table = self.as_table_mut().expect("unreachable");
+
+ if let Some((head, tail)) = split(key) {
+ table
+ .entry(head)
+ .or_insert_with(|| Value::Table(Table::new()))
+ .insert(tail, value);
+ } else {
+ table.insert(key.to_string(), value);
+ }
+ }
+
+ fn delete(&mut self, key: &str) -> Option<Value> {
+ if let Some((head, tail)) = split(key) {
+ self.get_mut(head)?.delete(tail)
+ } else if let Some(table) = self.as_table_mut() {
+ table.remove(key)
+ } else {
+ None
+ }
+ }
+}
+
+fn split(key: &str) -> Option<(&str, &str)> {
+ let ix = key.find('.')?;
+
+ let (head, tail) = key.split_at(ix);
+ // splitting will leave the "."
+ let tail = &tail[1..];
+
+ Some((head, tail))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::str::FromStr;
+
+ #[test]
+ fn read_simple_table() {
+ let src = "[table]";
+ let value = Value::from_str(src).unwrap();
+
+ let got = value.read("table").unwrap();
+
+ assert!(got.is_table());
+ }
+
+ #[test]
+ fn read_nested_item() {
+ let src = "[table]\nnested=true";
+ let value = Value::from_str(src).unwrap();
+
+ let got = value.read("table.nested").unwrap();
+
+ assert_eq!(got, &Value::Boolean(true));
+ }
+
+ #[test]
+ fn insert_item_at_top_level() {
+ let mut value = Value::Table(Table::default());
+ let item = Value::Boolean(true);
+
+ value.insert("first", item.clone());
+
+ assert_eq!(value.get("first").unwrap(), &item);
+ }
+
+ #[test]
+ fn insert_nested_item() {
+ let mut value = Value::Table(Table::default());
+ let item = Value::Boolean(true);
+
+ value.insert("first.second", item.clone());
+
+ let inserted = value.read("first.second").unwrap();
+ assert_eq!(inserted, &item);
+ }
+
+ #[test]
+ fn delete_a_top_level_item() {
+ let src = "top = true";
+ let mut value = Value::from_str(src).unwrap();
+
+ let got = value.delete("top").unwrap();
+
+ assert_eq!(got, Value::Boolean(true));
+ }
+
+ #[test]
+ fn delete_a_nested_item() {
+ let src = "[table]\n nested = true";
+ let mut value = Value::from_str(src).unwrap();
+
+ let got = value.delete("table.nested").unwrap();
+
+ assert_eq!(got, Value::Boolean(true));
+ }
+}