j7s_diagnostics/src/tree_view.rs

115 lines
3.1 KiB
Rust

//
// Copyright 2026 James Pace
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, v. 2.0.
//
use crate::diagnostic_graph::DiagnosticGraph;
use crate::diagnostic_status::DiagnosticStatus;
use crate::error::Result;
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
#[derive(Clone, Serialize, Deserialize)]
pub struct TreeView {
children: Vec<TreeViewNode>,
}
#[derive(Clone, Serialize, Deserialize)]
struct TreeViewNode {
id: String,
status: DiagnosticStatus,
children: Vec<TreeViewNode>,
}
impl TreeView {
fn get_nodes(key: &limbo_graph::Key, graph: &DiagnosticGraph) -> Result<Vec<TreeViewNode>> {
let children = graph.children_of(&key)?;
if children.len() == 0 {
return Ok(Vec::<TreeViewNode>::new());
}
let mut to_ret = Vec::<TreeViewNode>::new();
for child in children {
let status = graph.value_of(&child)?;
let node = TreeViewNode {
id: graph.full_name_from_key(&child)?,
status: status,
children: Self::get_nodes(&child, &graph)?,
};
to_ret.push(node);
}
return Ok(to_ret);
}
pub fn from_graph(graph: &DiagnosticGraph) -> Result<TreeView> {
let view = TreeView {
children: Self::get_nodes(&graph.root(), &graph)?,
};
Ok(view)
}
pub fn to_json(&self) -> Result<String> {
Ok(serde_json::to_string(self)?)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::*;
use alloc::collections::BTreeMap;
fn make_a_status_with_name(name: &str) -> DiagnosticStatus {
let level = DiagnosticLevel::OK;
let message = "I'm ok";
let hardware_id = "";
let values = BTreeMap::<String, String>::new();
DiagnosticStatus::new(
level,
name.to_owned(),
message.to_owned(),
hardware_id.to_owned(),
values,
)
}
#[test]
fn make_view() -> Result<()> {
let statuses = vec![
make_a_status_with_name("/a"),
make_a_status_with_name("/a/b"),
make_a_status_with_name("/a/b/c"),
make_a_status_with_name("/a/d/e"),
make_a_status_with_name("/a/d"),
];
let mut graph = DiagnosticGraph::new();
graph.add_status_vec(&statuses)?;
let view = TreeView::from_graph(&graph)?;
// First level is just a
assert!(view.children.len() == 1);
// a has children b and d.
assert!(view.children[0].children.len() == 2);
// regardless is this is b or d, it has one child.
// TODO: This isn't the best test.
assert!(view.children[0].children[0].children.len() == 1);
// Just to confirm it doesn't panic.
let _js = view.to_json()?;
Ok(())
}
}