Generate Graphviz dots
This commit is contained in:
parent
ca359c20e8
commit
8f2b55fede
22
src/lib.rs
22
src/lib.rs
@ -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 { .. }) {
|
||||||
|
35
src/main.rs
35
src/main.rs
@ -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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user