basic handling of "HashMap<String, String>" from dropshot

This commit is contained in:
Joshua M. Clulow 2021-10-01 22:09:10 -07:00
parent 3548096bdd
commit eec74acf18
1 changed files with 68 additions and 17 deletions

View File

@ -437,6 +437,10 @@ enum TypeDetails {
Object(BTreeMap<String, TypeId>), Object(BTreeMap<String, TypeId>),
NewType(TypeId), NewType(TypeId),
Enumeration(Vec<String>), Enumeration(Vec<String>),
/*
* A map with string keys and values of a specific type:
*/
Dictionary(TypeId),
} }
#[derive(Debug)] #[derive(Debug)]
@ -539,6 +543,19 @@ impl TypeSpace {
format!("[BASIC {} !NONAME?]", tid.0) format!("[BASIC {} !NONAME?]", tid.0)
} }
} }
TypeDetails::Dictionary(itid) => {
if let Some(ite) = self.id_to_entry.get(&itid) {
if let Some(n) = &ite.name {
return format!("dictionary of {} <{}>", n, itid.0);
}
}
/*
* If there is no name attached, we should try a
* recursive describe.
*/
format!("dictionary of {}", self.describe(itid))
}
TypeDetails::Array(itid) => { TypeDetails::Array(itid) => {
if let Some(ite) = self.id_to_entry.get(&itid) { if let Some(ite) = self.id_to_entry.get(&itid) {
if let Some(n) = &ite.name { if let Some(n) = &ite.name {
@ -621,6 +638,10 @@ impl TypeSpace {
TypeDetails::Array(itid) => { TypeDetails::Array(itid) => {
Ok(format!("Vec<{}>", self.render_type(itid, ctx)?)) Ok(format!("Vec<{}>", self.render_type(itid, ctx)?))
} }
TypeDetails::Dictionary(itid) => Ok(format!(
"std::collections::HashMap<String, {}>",
self.render_type(itid, ctx)?
)),
TypeDetails::Optional(itid) => { TypeDetails::Optional(itid) => {
Ok(format!("Option<{}>", self.render_type(itid, ctx)?)) Ok(format!("Option<{}>", self.render_type(itid, ctx)?))
} }
@ -743,31 +764,60 @@ impl TypeSpace {
* Object types must have a consistent name. * Object types must have a consistent name.
*/ */
let name = match (name, s.schema_data.title.as_deref()) { let name = match (name, s.schema_data.title.as_deref()) {
(Some(n), None) => n.to_string(), (Some(n), None) => Some(n.to_string()),
(None, Some(t)) => t.to_string(), (None, Some(t)) => Some(t.to_string()),
(Some(n), Some(t)) if n == t => n.to_string(), (Some(n), Some(t)) if n == t => Some(n.to_string()),
(Some(n), Some(t)) => { (Some(n), Some(t)) => {
bail!("names {} and {} conflict", n, t) bail!("names {} and {} conflict", n, t)
} }
(None, None) => bail!("types need a name? {:?}", s), (None, None) => None,
}; };
let mut omap = BTreeMap::new(); if let Some(name) = name {
for (n, rb) in o.properties.iter() { let mut omap = BTreeMap::new();
let itid = self.select_box(None, &rb)?; for (n, rb) in o.properties.iter() {
if o.required.contains(n) { let itid = self.select_box(None, &rb)?;
omap.insert(n.to_string(), itid); if o.required.contains(n) {
omap.insert(n.to_string(), itid);
} else {
/*
* This is an optional member.
*/
omap.insert(
n.to_string(),
self.id_for_optional(&itid),
);
}
}
(Some(name), TypeDetails::Object(omap))
} else {
/*
* An object type without a name may be intended as a
* map from strings to something else. If we also have
* no properties, required or otherwise, and we have an
* "additionalProperties" schema, we may be able to
* represent this as a HashMap<String, T>.
*/
use openapiv3::AdditionalProperties::Schema;
let tid = if o.properties.is_empty()
&& o.required.is_empty()
{
if let Some(Schema(s)) = &o.additional_properties {
Some(self.select(None, &s)?)
} else {
None
}
} else { } else {
/* None
* This is an optional member. };
*/
omap.insert( if let Some(tid) = tid {
n.to_string(), (None, TypeDetails::Dictionary(tid))
self.id_for_optional(&itid), } else {
); bail!("object types need a name? {:#?}", s);
} }
} }
(Some(name), TypeDetails::Object(omap))
} }
openapiv3::Type::String(st) => { openapiv3::Type::String(st) => {
use openapiv3::{ use openapiv3::{
@ -996,6 +1046,7 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
TypeDetails::Basic TypeDetails::Basic
| TypeDetails::Unknown | TypeDetails::Unknown
| TypeDetails::Array(_) | TypeDetails::Array(_)
| TypeDetails::Dictionary(_)
| TypeDetails::Optional(_) => None, | TypeDetails::Optional(_) => None,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();