Generate Graphviz dots

This commit is contained in:
Pierre HUBERT 2023-02-03 08:59:54 +01:00
parent ca359c20e8
commit 8f2b55fede
2 changed files with 56 additions and 1 deletions

View File

@ -46,6 +46,24 @@ pub enum NodeType {
Integer, Integer,
} }
impl NodeType {
pub fn can_have_children(&self) -> bool {
matches!(self, NodeType::Object { .. } | NodeType::Array { .. })
}
pub fn symbol(&self) -> &'static str {
match self {
NodeType::Null => "NULL",
NodeType::Boolean => "Bool",
NodeType::Array { .. } => "[]",
NodeType::Object { .. } => "{}",
NodeType::String => "str",
NodeType::Number => "num",
NodeType::Integer => "int",
}
}
}
#[derive(Debug, Clone, serde::Serialize)] #[derive(Debug, Clone, serde::Serialize)]
pub struct TreeNode { pub struct TreeNode {
pub name: String, pub name: String,
@ -60,6 +78,10 @@ pub struct TreeNode {
} }
impl TreeNode { impl TreeNode {
pub fn print_name(&self) -> String {
format!("{} {}", self.name, self.r#type.symbol())
}
/// Merge two TreeNode /// Merge two TreeNode
pub fn merge_with(self, other: Self) -> Self { pub fn merge_with(self, other: Self) -> Self {
if !matches!(self.r#type, NodeType::String | NodeType::Object { .. }) { if !matches!(self.r#type, NodeType::String | NodeType::Object { .. }) {

View File

@ -1,5 +1,6 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use openapi_parser::{build_tree, parse_schema}; use openapi_parser::{build_tree, parse_schema, NodeType, TreeNode};
use std::fmt::Write;
/// Dump the tree structure of a schema element as dot file /// Dump the tree structure of a schema element as dot file
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -25,6 +26,9 @@ struct Args {
enum Action { enum Action {
/// Dump as JSON /// Dump as JSON
Json, Json,
/// Dump as Graphviz graph
Graph,
} }
fn main() { fn main() {
@ -42,5 +46,34 @@ fn main() {
match args.action { match args.action {
Action::Json => println!("{}", serde_json::to_string(&tree).unwrap()), Action::Json => println!("{}", serde_json::to_string(&tree).unwrap()),
Action::Graph => println!("{}", graphviz_export(&tree)),
} }
} }
fn recurse_export(node: &TreeNode, parent_name: &str, out: &mut String) {
if !parent_name.is_empty() && node.r#type.can_have_children() {
writeln!(out, "\"{}\" -> \"{}\";", parent_name, node.print_name()).unwrap();
}
match &node.r#type {
NodeType::Array { item } => {
recurse_export(item, &node.print_name(), out);
}
NodeType::Object { children, .. } => {
for child in children {
recurse_export(child, &node.print_name(), out);
}
}
_ => {}
}
}
fn graphviz_export(tree: &TreeNode) -> String {
let mut out = "digraph G {\n".to_string();
recurse_export(tree, "", &mut out);
out.push_str("}\n");
out
}