path parameters first, by position; then query parameters, by name
This commit is contained in:
parent
aab5061b56
commit
2a319675b1
49
src/main.rs
49
src/main.rs
|
@ -1171,7 +1171,15 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
|
||||||
}
|
}
|
||||||
a(" &self,");
|
a(" &self,");
|
||||||
|
|
||||||
for par in o.parameters.iter() {
|
/*
|
||||||
|
* The order of parameters in the specification is effectively
|
||||||
|
* arbitrary, and both path and query style parameters end up
|
||||||
|
* mingled in the same list.
|
||||||
|
*/
|
||||||
|
let mut parms = o
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.map(|par| {
|
||||||
match par.item()? {
|
match par.item()? {
|
||||||
openapiv3::Parameter::Path {
|
openapiv3::Parameter::Path {
|
||||||
parameter_data,
|
parameter_data,
|
||||||
|
@ -1183,10 +1191,11 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
|
||||||
assert!(parameter_data.required);
|
assert!(parameter_data.required);
|
||||||
|
|
||||||
let nam = ¶meter_data.name;
|
let nam = ¶meter_data.name;
|
||||||
let tid = ts.select(None, parameter_data.schema()?)?;
|
let tid =
|
||||||
|
ts.select(None, parameter_data.schema()?)?;
|
||||||
let typ =
|
let typ =
|
||||||
ts.render_type(&tid, UseContext::Parameter)?;
|
ts.render_type(&tid, UseContext::Parameter)?;
|
||||||
a(&format!(" {}: {},", nam, typ));
|
return Ok((true, nam, typ));
|
||||||
}
|
}
|
||||||
openapiv3::Parameter::Query {
|
openapiv3::Parameter::Query {
|
||||||
parameter_data,
|
parameter_data,
|
||||||
|
@ -1201,7 +1210,8 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let nam = ¶meter_data.name;
|
let nam = ¶meter_data.name;
|
||||||
let tid = ts.select(None, parameter_data.schema()?)?;
|
let tid =
|
||||||
|
ts.select(None, parameter_data.schema()?)?;
|
||||||
let tid = if parameter_data.required {
|
let tid = if parameter_data.required {
|
||||||
tid
|
tid
|
||||||
} else {
|
} else {
|
||||||
|
@ -1213,14 +1223,38 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
|
||||||
};
|
};
|
||||||
let typ =
|
let typ =
|
||||||
ts.render_type(&tid, UseContext::Parameter)?;
|
ts.render_type(&tid, UseContext::Parameter)?;
|
||||||
a(&format!(" {}: {},", nam, typ));
|
query.push((
|
||||||
|
nam.to_string(),
|
||||||
query.push((nam.to_string(), !parameter_data.required));
|
!parameter_data.required,
|
||||||
|
));
|
||||||
|
return Ok((false, nam, typ));
|
||||||
}
|
}
|
||||||
x => bail!("unhandled parameter type: {:#?}", x),
|
x => bail!("unhandled parameter type: {:#?}", x),
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deal first with path parameters, ordered by their position in the
|
||||||
|
* path template string.
|
||||||
|
*/
|
||||||
|
let tmp = template::parse(p)?;
|
||||||
|
for pn in tmp.names() {
|
||||||
|
let par = parms.iter().find(|p| p.0 && p.1 == &pn).unwrap();
|
||||||
|
a(&format!(" {}: {},", par.1, par.2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Second, include query parameters, ordered by parameter name.
|
||||||
|
*/
|
||||||
|
parms.sort_by(|a, b| a.1.cmp(&b.1));
|
||||||
|
for par in parms.iter().filter(|p| !p.0) {
|
||||||
|
a(&format!(" {}: {},", par.1, par.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include the body parameter, if there is one, last in the list:
|
||||||
|
*/
|
||||||
if let Some(bp) = &body_param {
|
if let Some(bp) = &body_param {
|
||||||
a(&format!(" body: {},", bp));
|
a(&format!(" body: {},", bp));
|
||||||
}
|
}
|
||||||
|
@ -1289,7 +1323,6 @@ fn gen(api: &OpenAPI, ts: &mut TypeSpace) -> Result<String> {
|
||||||
/*
|
/*
|
||||||
* Generate the URL for the request.
|
* Generate the URL for the request.
|
||||||
*/
|
*/
|
||||||
let tmp = template::parse(p)?;
|
|
||||||
a(&tmp.compile());
|
a(&tmp.compile());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -35,6 +35,16 @@ impl Template {
|
||||||
out.push_str(" );\n");
|
out.push_str(" );\n");
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn names(&self) -> Vec<String> {
|
||||||
|
self.components
|
||||||
|
.iter()
|
||||||
|
.filter_map(|c| match c {
|
||||||
|
Component::Parameter(name) => Some(name.to_string()),
|
||||||
|
Component::Constant(_) => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(t: &str) -> Result<Template> {
|
pub fn parse(t: &str) -> Result<Template> {
|
||||||
|
@ -159,6 +169,25 @@ mod test {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn names() -> Result<()> {
|
||||||
|
let trials = vec![
|
||||||
|
("/info", vec![]),
|
||||||
|
("/measure/{number}", vec!["number".to_string()]),
|
||||||
|
(
|
||||||
|
"/measure/{one}/{two}/and/{three}/yeah",
|
||||||
|
vec!["one".to_string(), "two".to_string(), "three".to_string()],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (path, want) in trials.iter() {
|
||||||
|
let t = parse(path).with_context(|| anyhow!("path {}", path))?;
|
||||||
|
assert_eq!(&t.names(), want);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compile() -> Result<()> {
|
fn compile() -> Result<()> {
|
||||||
let t = parse("/measure/{number}")?;
|
let t = parse("/measure/{number}")?;
|
||||||
|
|
Loading…
Reference in New Issue