diff --git a/src/analyzer.rs b/src/analyzer.rs index c1315fa..3bc2141 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -12,6 +12,7 @@ const IGNORED_KEYS: [&str; 3] = ["metadata", "apiVersion", "kind"]; #[derive(Default)] pub struct Config { pub no_condition: bool, + pub btreemap: bool, } /// Scan a schema for structs and members, and recurse to find all structs @@ -251,7 +252,8 @@ fn extract_container( dict_key = Some("serde_json::Value".into()); } if let Some(dict) = dict_key { - format!("BTreeMap", dict) + let map_type = if cfg.btreemap { "BTreeMap" } else { "HashMap" }; + format!("{}", map_type, dict) } else { format!("{}{}", stack, key.to_upper_camel_case()) } @@ -270,7 +272,7 @@ fn extract_container( "integer" => extract_integer_type(value)?, "array" => { // recurse through repeated arrays until we find a concrete type (keep track of how deep we went) - let (mut array_type, recurse_level) = array_recurse_for_type(value, stack, key, 1)?; + let (mut array_type, recurse_level) = array_recurse_for_type(value, stack, key, 1, cfg)?; trace!("got array {} for {} in level {}", array_type, key, recurse_level); if !cfg.no_condition && key == "conditions" && is_conditions(value) { array_type = "Vec".into(); @@ -405,6 +407,7 @@ fn array_recurse_for_type( stack: &str, key: &str, level: u8, + cfg: &Config, ) -> Result<(String, u8)> { if let Some(items) = &value.items { match items { @@ -422,7 +425,8 @@ fn array_recurse_for_type( } let vec_value = if let Some(dict_value) = dict_value { - format!("BTreeMap") + let map_type = if cfg.btreemap { "BTreeMap" } else { "HashMap" }; + format!("{map_type}") } else { let structsuffix = key.to_upper_camel_case(); format!("{stack}{structsuffix}") @@ -435,7 +439,7 @@ fn array_recurse_for_type( "date" => Ok((format!("Vec<{}>", extract_date_type(value)?), level)), "number" => Ok((format!("Vec<{}>", extract_number_type(value)?), level)), "integer" => Ok((format!("Vec<{}>", extract_integer_type(value)?), level)), - "array" => Ok(array_recurse_for_type(s, stack, key, level + 1)?), + "array" => Ok(array_recurse_for_type(s, stack, key, level + 1, cfg)?), unknown => { bail!("unsupported recursive array type \"{unknown}\" for {key}") } @@ -580,7 +584,7 @@ mod test { // should have a member with a key to the map: let map = &root.members[0]; assert_eq!(map.name, "validationsInfo"); - assert_eq!(map.type_, "Option>"); + assert_eq!(map.type_, "Option>"); // should have a separate struct let other = &structs[1]; assert_eq!(other.name, "AgentValidationsInfo"); @@ -630,7 +634,7 @@ type: object assert_eq!(server_selector.level, 1); let match_labels = &server_selector.members[0]; assert_eq!(match_labels.name, "matchLabels"); - assert_eq!(match_labels.type_, "BTreeMap"); + assert_eq!(match_labels.type_, "HashMap"); } #[test] @@ -679,7 +683,7 @@ type: object assert_eq!(root.name, "Options"); assert_eq!(root.level, 0); assert_eq!(&root.members[0].name, "options"); - assert_eq!(&root.members[0].type_, "Option>"); + assert_eq!(&root.members[0].type_, "Option>"); } #[test] @@ -857,7 +861,7 @@ type: object assert_eq!(&ps.members[0].name, "MatchExpressions"); assert_eq!(&ps.members[0].type_, "Vec"); + assert_eq!(&ps.members[1].type_, "HashMap"); // should have the inner struct match expressions let me = &structs[2]; @@ -926,7 +930,7 @@ type: object // should have an params member: let member = &eps.members[0]; assert_eq!(member.name, "params"); - assert_eq!(member.type_, "Option>"); + assert_eq!(member.type_, "Option>"); } #[test] @@ -990,7 +994,7 @@ type: object assert_eq!(from.name, "from"); assert_eq!(to.name, "to"); assert_eq!(from.type_, "Option"); - assert_eq!(to.type_, "Option>"); + assert_eq!(to.type_, "Option>"); } #[test] @@ -1083,7 +1087,7 @@ type: object assert_eq!(&root.members[0].name, "jwtTokensByRole"); assert_eq!( &root.members[0].type_, - "Option>" + "Option>" ); let role = &structs[1]; assert_eq!(role.level, 1); @@ -1145,7 +1149,7 @@ type: object assert_eq!(structs[0].members[0].name, "records"); assert_eq!( structs[0].members[0].type_, - "Option>>" + "Option>>" ); } diff --git a/src/main.rs b/src/main.rs index 8182b21..b0ed617 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,6 +96,12 @@ struct Kopium { /// Condition API instead of generating a custom definition. #[arg(long)] no_condition: bool, + + /// Use BTreeMap to represent the map (additionalProperties) types. + /// + /// If false, HashMap is defaulted in representing the map types. + #[arg(long)] + btreemap: bool, } #[derive(Clone, Copy, Debug, Subcommand)] @@ -192,6 +198,7 @@ impl Kopium { log::debug!("schema: {}", serde_json::to_string_pretty(&schema)?); let cfg = Config { no_condition: self.no_condition, + btreemap: self.btreemap, }; let structs = analyze(schema, kind, cfg)? .rename()