diff --git a/src/lib.rs b/src/lib.rs index 63772ca..9820e51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,24 @@ pub enum NodeType { 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)] pub struct TreeNode { pub name: String, @@ -60,6 +78,10 @@ pub struct TreeNode { } impl TreeNode { + pub fn print_name(&self) -> String { + format!("{} {}", self.name, self.r#type.symbol()) + } + /// Merge two TreeNode pub fn merge_with(self, other: Self) -> Self { if !matches!(self.r#type, NodeType::String | NodeType::Object { .. }) { diff --git a/src/main.rs b/src/main.rs index 1257065..9dd7205 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ 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 #[derive(Parser, Debug)] @@ -25,6 +26,9 @@ struct Args { enum Action { /// Dump as JSON Json, + + /// Dump as Graphviz graph + Graph, } fn main() { @@ -42,5 +46,34 @@ fn main() { match args.action { 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 +}