228 lines
6.8 KiB
Rust
228 lines
6.8 KiB
Rust
#![allow(non_snake_case)]
|
|
use anyhow::anyhow;
|
|
use std::collections::BTreeMap;
|
|
|
|
#[cxx::bridge(namespace = "j7s_diagnostics_cxx")]
|
|
mod ffi {
|
|
// Shared structs whose fields can be seen in both C++ and Rust.
|
|
#[derive(Clone, PartialOrd, PartialEq, Default)]
|
|
pub enum DiagnosticLevel {
|
|
#[default]
|
|
UNSET,
|
|
OK,
|
|
WARN,
|
|
ERROR,
|
|
STALE,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct DiagnosticStatus {
|
|
level: DiagnosticLevel,
|
|
name: String,
|
|
message: String,
|
|
hardware_id: String,
|
|
values: Box<StringMap>,
|
|
}
|
|
|
|
extern "Rust" {
|
|
// Functions in here can be seen on both sides, but are
|
|
// defined in rust.
|
|
// types can be seen in both languages, but only opaquely in C++.
|
|
#[Self = "DiagnosticStatus"]
|
|
fn build() -> DiagnosticStatus;
|
|
|
|
type OptionalString;
|
|
#[Self = "OptionalString"]
|
|
fn some(val: String) -> Box<OptionalString>;
|
|
#[Self = "OptionalString"]
|
|
fn none() -> Box<OptionalString>;
|
|
fn is_some(self: &OptionalString) -> bool;
|
|
fn value(self: &OptionalString) -> Result<String>;
|
|
|
|
type StringMap;
|
|
#[Self = "StringMap"]
|
|
fn build() -> Box<StringMap>;
|
|
fn get(self: &StringMap, key: &String) -> Box<OptionalString>;
|
|
fn insert(self: &mut StringMap, key: String, value: String);
|
|
fn keys(self: &StringMap) -> Vec<String>;
|
|
|
|
type DiagnosticTree;
|
|
#[Self = "DiagnosticTree"]
|
|
fn build() -> Box<DiagnosticTree>;
|
|
fn add_statuses(self: &mut DiagnosticTree, statuses: &Vec<DiagnosticStatus>) -> Result<()>;
|
|
fn add_status(self: &mut DiagnosticTree, status: &DiagnosticStatus) -> Result<()>;
|
|
fn reconcile(self: &mut DiagnosticTree) -> Result<()>;
|
|
fn aggregate(self: &DiagnosticTree) -> Result<Vec<DiagnosticStatus>>;
|
|
|
|
}
|
|
}
|
|
|
|
fn diagnostic_level_to_rust(cpp: &crate::ffi::DiagnosticLevel) -> j7s_diagnostics::DiagnosticLevel {
|
|
match cpp {
|
|
&crate::ffi::DiagnosticLevel::UNSET => j7s_diagnostics::DiagnosticLevel::UNSET,
|
|
&crate::ffi::DiagnosticLevel::OK => j7s_diagnostics::DiagnosticLevel::OK,
|
|
&crate::ffi::DiagnosticLevel::WARN => j7s_diagnostics::DiagnosticLevel::WARN,
|
|
&crate::ffi::DiagnosticLevel::ERROR => j7s_diagnostics::DiagnosticLevel::ERROR,
|
|
&crate::ffi::DiagnosticLevel::STALE => j7s_diagnostics::DiagnosticLevel::STALE,
|
|
_ => j7s_diagnostics::DiagnosticLevel::UNSET,
|
|
}
|
|
}
|
|
|
|
fn diagnostic_level_from_rust(
|
|
rust: &j7s_diagnostics::DiagnosticLevel,
|
|
) -> crate::ffi::DiagnosticLevel {
|
|
match rust {
|
|
&j7s_diagnostics::DiagnosticLevel::UNSET => crate::ffi::DiagnosticLevel::UNSET,
|
|
&j7s_diagnostics::DiagnosticLevel::OK => crate::ffi::DiagnosticLevel::OK,
|
|
&j7s_diagnostics::DiagnosticLevel::WARN => crate::ffi::DiagnosticLevel::WARN,
|
|
&j7s_diagnostics::DiagnosticLevel::ERROR => crate::ffi::DiagnosticLevel::ERROR,
|
|
&j7s_diagnostics::DiagnosticLevel::STALE => crate::ffi::DiagnosticLevel::STALE,
|
|
}
|
|
}
|
|
|
|
fn diagnostic_status_to_rust(
|
|
cpp: &crate::ffi::DiagnosticStatus,
|
|
) -> j7s_diagnostics::DiagnosticStatus {
|
|
j7s_diagnostics::DiagnosticStatus::new(
|
|
diagnostic_level_to_rust(&cpp.level),
|
|
cpp.name.clone(),
|
|
cpp.message.clone(),
|
|
cpp.hardware_id.clone(),
|
|
cpp.values.to_btree(),
|
|
)
|
|
}
|
|
|
|
fn diagnostic_status_from_rust(
|
|
rust: &j7s_diagnostics::DiagnosticStatus,
|
|
) -> crate::ffi::DiagnosticStatus {
|
|
crate::ffi::DiagnosticStatus {
|
|
level: diagnostic_level_from_rust(&rust.level()),
|
|
name: rust.name(),
|
|
message: rust.message(),
|
|
hardware_id: rust.hardware_id(),
|
|
values: Box::new(StringMap::from_btree(rust.values())),
|
|
}
|
|
}
|
|
|
|
impl crate::ffi::DiagnosticStatus {
|
|
fn build() -> Self {
|
|
Self {
|
|
level: crate::ffi::DiagnosticLevel::default(),
|
|
name: String::default(),
|
|
message: String::default(),
|
|
hardware_id: String::default(),
|
|
values: StringMap::build(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct DiagnosticTree {
|
|
graph: j7s_diagnostics::DiagnosticGraph,
|
|
}
|
|
|
|
impl DiagnosticTree {
|
|
pub fn build() -> Box<DiagnosticTree> {
|
|
let graph = j7s_diagnostics::DiagnosticGraph::new();
|
|
let tree = DiagnosticTree { graph: graph };
|
|
Box::new(tree)
|
|
}
|
|
|
|
pub fn add_statuses(
|
|
self: &mut DiagnosticTree,
|
|
statuses: &Vec<crate::ffi::DiagnosticStatus>,
|
|
) -> anyhow::Result<()> {
|
|
let mut converted_statuses = Vec::new();
|
|
for status in statuses.iter() {
|
|
converted_statuses.push(diagnostic_status_to_rust(&status));
|
|
}
|
|
Ok(self.graph.add_status_vec(&converted_statuses)?)
|
|
}
|
|
|
|
fn add_status(self: &mut DiagnosticTree, status: &crate::ffi::DiagnosticStatus) -> anyhow::Result<()> {
|
|
Ok(self.graph.add_status(diagnostic_status_to_rust(&status))?)
|
|
}
|
|
|
|
pub fn reconcile(self: &mut DiagnosticTree) -> anyhow::Result<()> {
|
|
Ok(self.graph.reconcile_levels()?)
|
|
}
|
|
|
|
fn aggregate(self: &DiagnosticTree) -> anyhow::Result<Vec<crate::ffi::DiagnosticStatus>> {
|
|
let statuses = self.graph.export_graph()?;
|
|
let mut converted_statuses = Vec::new();
|
|
for status in statuses.iter() {
|
|
converted_statuses.push(diagnostic_status_from_rust(&status));
|
|
}
|
|
Ok(converted_statuses)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct OptionalString {
|
|
val: Option<String>,
|
|
}
|
|
|
|
impl OptionalString {
|
|
pub fn some(val: String) -> Box<Self> {
|
|
let raw = Self { val: Some(val) };
|
|
Box::new(raw)
|
|
}
|
|
|
|
pub fn none() -> Box<Self> {
|
|
let raw = Self { val: None };
|
|
Box::new(raw)
|
|
}
|
|
|
|
pub fn is_some(&self) -> bool {
|
|
self.val.is_some()
|
|
}
|
|
|
|
pub fn value(&self) -> anyhow::Result<String> {
|
|
match &self.val {
|
|
None => Err(anyhow!("Option not valid.")),
|
|
Some(val) => Ok(val.clone()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct StringMap {
|
|
map: BTreeMap<String, String>,
|
|
}
|
|
|
|
impl StringMap {
|
|
pub fn build() -> Box<Self> {
|
|
let raw = Self {
|
|
map: BTreeMap::<String, String>::new(),
|
|
};
|
|
Box::new(raw)
|
|
}
|
|
|
|
pub fn from_btree(map: BTreeMap<String, String>) -> Self {
|
|
Self { map: map }
|
|
}
|
|
|
|
fn keys(&self) -> Vec<String> {
|
|
self.map.keys().map(|s| s.clone()).collect()
|
|
}
|
|
|
|
pub fn to_btree(&self) -> BTreeMap<String, String> {
|
|
self.map.clone()
|
|
}
|
|
|
|
pub fn get(&self, key: &String) -> Box<OptionalString> {
|
|
match self.map.get(key) {
|
|
None => OptionalString::none(),
|
|
Some(val) => OptionalString::some(val.clone()),
|
|
}
|
|
}
|
|
|
|
pub fn insert(&mut self, key: String, value: String) {
|
|
let _ = self.map.insert(key, value);
|
|
}
|
|
|
|
pub fn to_box(self) -> Box<StringMap> {
|
|
Box::new(self)
|
|
}
|
|
}
|