src/tools/disks/zpool_status.rs - cleanup: use struct StackItem instead of tuple

This commit is contained in:
Dietmar Maurer 2020-06-19 18:47:29 +02:00
parent 5d88c3a1c8
commit 1cb46c6f65
1 changed files with 34 additions and 28 deletions

View File

@ -194,13 +194,21 @@ where
use serde_json::Map; use serde_json::Map;
use std::mem::replace; use std::mem::replace;
let mut stack = Vec::<(Map<String, Value>, u64, Vec<Value>)>::new(); // (node, level, children) struct StackItem {
// hold current node and the children of the current parent (as that's where we insert) node: Map<String, Value>,
let mut cur_node = Map::<String, Value>::new(); level: u64,
let mut cur_level = 0; children_of_parent: Vec<Value>,
let mut children_of_parent = Vec::new(); }
cur_node.insert("name".to_string(), Value::String("root".to_string())); let mut stack = Vec::<StackItem>::new();
// hold current node and the children of the current parent (as that's where we insert)
let mut cur = StackItem {
node: Map::<String, Value>::new(),
level: 0,
children_of_parent: Vec::new(),
};
cur.node.insert("name".to_string(), Value::String("root".to_string()));
for item in items { for item in items {
let (node, node_level) = to_node(&item); let (node, node_level) = to_node(&item);
@ -213,48 +221,46 @@ where
node.insert("leaf".to_string(), Value::Bool(true)); node.insert("leaf".to_string(), Value::Bool(true));
// if required, go back up (possibly multiple levels): // if required, go back up (possibly multiple levels):
while vdev_level < cur_level { while vdev_level < cur.level {
children_of_parent.push(Value::Object(cur_node)); cur.children_of_parent.push(Value::Object(cur.node));
let mut prev = stack.pop().unwrap(); let mut prev = stack.pop().unwrap();
prev.0.insert("children".to_string(), Value::Array(children_of_parent)); prev.node.insert("children".to_string(), Value::Array(cur.children_of_parent));
prev.0.insert("leaf".to_string(), Value::Bool(false)); prev.node.insert("leaf".to_string(), Value::Bool(false));
cur_node = prev.0; cur = prev;
cur_level = prev.1;
children_of_parent = prev.2;
if vdev_level > cur_level { if vdev_level > cur.level {
// when we encounter misimatching levels like "0, 2, 1" instead of "0, 1, 2, 1" // when we encounter misimatching levels like "0, 2, 1" instead of "0, 1, 2, 1"
bail!("broken indentation between levels"); bail!("broken indentation between levels");
} }
} }
if vdev_level > cur_level { if vdev_level > cur.level {
// indented further, push our current state and start a new "map" // indented further, push our current state and start a new "map"
stack.push(( stack.push(StackItem {
replace(&mut cur_node, node), node: replace(&mut cur.node, node),
replace(&mut cur_level, vdev_level), level: replace(&mut cur.level, vdev_level),
replace(&mut children_of_parent, Vec::new()), children_of_parent: replace(&mut cur.children_of_parent, Vec::new()),
)); }); cur.children_of_parent = prev.children_of_parent;
} else { } else {
// same indentation level, add to children of the previous level: // same indentation level, add to children of the previous level:
children_of_parent.push(Value::Object( cur.children_of_parent.push(Value::Object(
replace(&mut cur_node, node), replace(&mut cur.node, node),
)); ));
} }
} }
while !stack.is_empty() { while !stack.is_empty() {
children_of_parent.push(Value::Object(cur_node)); cur.children_of_parent.push(Value::Object(cur.node));
let mut prev = stack.pop().unwrap(); let mut prev = stack.pop().unwrap();
prev.0.insert("children".to_string(), Value::Array(children_of_parent)); prev.node.insert("children".to_string(), Value::Array(cur.children_of_parent));
if !stack.is_empty() { if !stack.is_empty() {
prev.0.insert("leaf".to_string(), Value::Bool(false)); prev.node.insert("leaf".to_string(), Value::Bool(false));
} }
cur_node = prev.0; cur = prev;
children_of_parent = prev.2;
} }
Ok(Value::Object(cur_node)) Ok(Value::Object(cur.node))
} }
#[test] #[test]