Skip to content

Commit

Permalink
Added btreemap flag to toggle BTreeMap/HashMap for map types
Browse files Browse the repository at this point in the history
Added boolean flag `btreemap` that toggles whether to to use BTreeMap or
HashMap for representing map/additional_properties type.

Fixes: #78

Signed-off-by: tyrone-wu <[email protected]>
  • Loading branch information
tyrone-wu committed Mar 31, 2024
1 parent 96035d0 commit b569dee
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
28 changes: 16 additions & 12 deletions src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -251,7 +252,8 @@ fn extract_container(
dict_key = Some("serde_json::Value".into());
}
if let Some(dict) = dict_key {
format!("BTreeMap<String, {}>", dict)
let map_type = if cfg.btreemap { "BTreeMap" } else { "HashMap" };
format!("{}<String, {}>", map_type, dict)
} else {
format!("{}{}", stack, key.to_upper_camel_case())
}
Expand All @@ -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<Condition>".into();
Expand Down Expand Up @@ -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 {
Expand All @@ -422,7 +425,8 @@ fn array_recurse_for_type(
}

let vec_value = if let Some(dict_value) = dict_value {
format!("BTreeMap<String, {dict_value}>")
let map_type = if cfg.btreemap { "BTreeMap" } else { "HashMap" };
format!("{map_type}<String, {dict_value}>")
} else {
let structsuffix = key.to_upper_camel_case();
format!("{stack}{structsuffix}")
Expand All @@ -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}")
}
Expand Down Expand Up @@ -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<BTreeMap<String, AgentValidationsInfo>>");
assert_eq!(map.type_, "Option<HashMap<String, AgentValidationsInfo>>");
// should have a separate struct
let other = &structs[1];
assert_eq!(other.name, "AgentValidationsInfo");
Expand Down Expand Up @@ -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<String, serde_json::Value>");
assert_eq!(match_labels.type_, "HashMap<String, serde_json::Value>");
}

#[test]
Expand Down Expand Up @@ -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<BTreeMap<String, bool>>");
assert_eq!(&root.members[0].type_, "Option<HashMap<String, bool>>");
}

#[test]
Expand Down Expand Up @@ -857,7 +861,7 @@ type: object
assert_eq!(&ps.members[0].name, "MatchExpressions");
assert_eq!(&ps.members[0].type_, "Vec<ServerPodSelectorMatchExpressions");
assert_eq!(&ps.members[1].name, "MatchLabels");
assert_eq!(&ps.members[1].type_, "BTreeMap<String, String>");
assert_eq!(&ps.members[1].type_, "HashMap<String, String>");

// should have the inner struct match expressions
let me = &structs[2];
Expand Down Expand Up @@ -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<BTreeMap<String, String>>");
assert_eq!(member.type_, "Option<HashMap<String, String>>");
}

#[test]
Expand Down Expand Up @@ -990,7 +994,7 @@ type: object
assert_eq!(from.name, "from");
assert_eq!(to.name, "to");
assert_eq!(from.type_, "Option<String>");
assert_eq!(to.type_, "Option<BTreeMap<String, i32>>");
assert_eq!(to.type_, "Option<HashMap<String, i32>>");
}

#[test]
Expand Down Expand Up @@ -1083,7 +1087,7 @@ type: object
assert_eq!(&root.members[0].name, "jwtTokensByRole");
assert_eq!(
&root.members[0].type_,
"Option<BTreeMap<String, AppProjectStatusJwtTokensByRole>>"
"Option<HashMap<String, AppProjectStatusJwtTokensByRole>>"
);
let role = &structs[1];
assert_eq!(role.level, 1);
Expand Down Expand Up @@ -1145,7 +1149,7 @@ type: object
assert_eq!(structs[0].members[0].name, "records");
assert_eq!(
structs[0].members[0].type_,
"Option<Vec<BTreeMap<String, String>>>"
"Option<Vec<HashMap<String, String>>>"
);
}

Expand Down
7 changes: 7 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit b569dee

Please sign in to comment.