87 lines
2.3 KiB
Rust
87 lines
2.3 KiB
Rust
|
// Copyright 2022 Oxide Computer Company
|
||
|
|
||
|
use convert_case::{Case, Casing};
|
||
|
use indexmap::IndexMap;
|
||
|
use openapiv3::{
|
||
|
Components, Parameter, ReferenceOr, RequestBody, Response, Schema,
|
||
|
};
|
||
|
use unicode_xid::UnicodeXID;
|
||
|
|
||
|
use crate::Result;
|
||
|
|
||
|
pub(crate) trait ReferenceOrExt<T: ComponentLookup> {
|
||
|
fn item<'a>(&'a self, components: &'a Option<Components>) -> Result<&'a T>;
|
||
|
}
|
||
|
pub(crate) trait ComponentLookup: Sized {
|
||
|
fn get_components(
|
||
|
components: &Components,
|
||
|
) -> &IndexMap<String, ReferenceOr<Self>>;
|
||
|
}
|
||
|
|
||
|
impl<T: ComponentLookup> ReferenceOrExt<T> for openapiv3::ReferenceOr<T> {
|
||
|
fn item<'a>(&'a self, components: &'a Option<Components>) -> Result<&'a T> {
|
||
|
match self {
|
||
|
ReferenceOr::Item(item) => Ok(item),
|
||
|
ReferenceOr::Reference { reference } => {
|
||
|
let idx = reference.rfind('/').unwrap();
|
||
|
let key = &reference[idx + 1..];
|
||
|
let parameters =
|
||
|
T::get_components(components.as_ref().unwrap());
|
||
|
parameters.get(key).unwrap().item(components)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ComponentLookup for Parameter {
|
||
|
fn get_components(
|
||
|
components: &Components,
|
||
|
) -> &IndexMap<String, ReferenceOr<Self>> {
|
||
|
&components.parameters
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ComponentLookup for RequestBody {
|
||
|
fn get_components(
|
||
|
components: &Components,
|
||
|
) -> &IndexMap<String, ReferenceOr<Self>> {
|
||
|
&components.request_bodies
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ComponentLookup for Response {
|
||
|
fn get_components(
|
||
|
components: &Components,
|
||
|
) -> &IndexMap<String, ReferenceOr<Self>> {
|
||
|
&components.responses
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ComponentLookup for Schema {
|
||
|
fn get_components(
|
||
|
components: &Components,
|
||
|
) -> &IndexMap<String, ReferenceOr<Self>> {
|
||
|
&components.schemas
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub(crate) fn sanitize(input: &str, case: Case) -> String {
|
||
|
let out = input
|
||
|
.replace("'", "")
|
||
|
.replace(|c: char| !c.is_xid_continue(), "-")
|
||
|
.to_case(case);
|
||
|
|
||
|
let out = match out.chars().next() {
|
||
|
None => "x".to_case(case),
|
||
|
Some(c) if c.is_xid_start() => out,
|
||
|
Some(_) => format!("_{}", out),
|
||
|
};
|
||
|
|
||
|
// Make sure the string is a valid Rust identifier.
|
||
|
if syn::parse_str::<syn::Ident>(&out).is_ok() {
|
||
|
out
|
||
|
} else {
|
||
|
format!("{}_", out)
|
||
|
}
|
||
|
}
|