Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub(crate) mod struct_enum;
pub(crate) mod types;

use aide::openapi;
use anyhow::bail;
use serde::{Deserialize, Serialize};

use crate::cli_v1::IncludeMode;
Expand Down Expand Up @@ -46,18 +47,11 @@ impl Api {

Ok(Self { resources, types })
}
}

impl FromIterator<Api> for Api {
fn from_iter<T: IntoIterator<Item = Api>>(into_iter: T) -> Self {
let mut iter = into_iter.into_iter();

let mut api = iter.next().unwrap_or_default();
for item in iter {
merge_resources(&mut api.resources, item.resources);
api.types.extend(item.types);
}
api
pub(crate) fn merge(mut self, other: Self) -> anyhow::Result<Self> {
merge_resources(&mut self.resources, other.resources);
merge_types(&mut self.types, other.types)?;
Ok(self)
}
}

Expand Down Expand Up @@ -87,6 +81,23 @@ fn merge_resources(dst: &mut Resources, src: Resources) {
}
}

fn merge_types(dst: &mut Types, src: Types) -> anyhow::Result<()> {
for (name, ty) in src {
match dst.entry(name) {
btree_map::Entry::Vacant(entry) => {
entry.insert(ty);
}
btree_map::Entry::Occupied(entry) => {
if *entry.get() != ty {
bail!("mismatching definitions for {}", entry.key());
}
}
}
}

Ok(())
}

pub(crate) fn get_schema_name(maybe_ref: Option<&str>) -> Option<String> {
let r = maybe_ref?;
let schema_name = r.strip_prefix("#/components/schemas/");
Expand Down
14 changes: 7 additions & 7 deletions src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub(crate) fn from_referenced_components(
types
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
pub(crate) struct Type {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -160,7 +160,7 @@ fn fields_referenced_schemas(fields: &[Field]) -> BTreeSet<&str> {
.collect()
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub(crate) enum TypeData {
Struct {
Expand Down Expand Up @@ -271,7 +271,7 @@ impl TypeData {
}
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
#[serde(tag = "repr", rename_all = "snake_case")]
pub(crate) enum StructEnumRepr {
// add more variants here to support other enum representations
Expand Down Expand Up @@ -303,7 +303,7 @@ impl StructEnumRepr {
}
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
pub(crate) struct Field {
name: String,
#[serde(serialize_with = "serialize_field_type")]
Expand Down Expand Up @@ -346,7 +346,7 @@ impl Field {
}
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
#[serde(tag = "type", rename_all = "camelCase")]
pub(crate) enum EnumVariantType {
Struct {
Expand All @@ -360,7 +360,7 @@ pub(crate) enum EnumVariantType {
},
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
pub(crate) struct SimpleVariant {
/// Discriminator value that identifies this variant.
pub name: String,
Expand All @@ -371,7 +371,7 @@ pub(crate) struct SimpleVariant {
/// Supported field type.
///
/// Equivalent to openapi's `type` + `format` + `$ref`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(tag = "id")]
pub(crate) enum FieldType {
Bool,
Expand Down
15 changes: 8 additions & 7 deletions src/cli_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ pub fn run_cli_v1_main() -> anyhow::Result<()> {

let api = input_files
.iter()
.map(|input_file| {
.try_fold(Api::default(), |result, input_file| {
let input_file = Path::new(input_file);
let input_file_ext = input_file
.extension()
.context("input file must have a file extension")?;
let input_file_contents = fs::read_to_string(input_file)?;

if input_file_ext == "json" {
let api = if input_file_ext == "json" {
let spec: OpenApi = serde_json::from_str(&input_file_contents)
.context("failed to parse OpenAPI spec")?;

Expand All @@ -113,14 +113,15 @@ pub fn run_cli_v1_main() -> anyhow::Result<()> {
&excluded_operations,
&specified_operations,
)
.context("converting OpenAPI spec to our own representation")
.context("converting OpenAPI spec to our own representation")?
} else if input_file_ext == "ron" {
ron::from_str(&input_file_contents).context("parsing ron file")
ron::from_str(&input_file_contents).context("parsing ron file")?
} else {
bail!("input file extension must be .json or .ron");
}
})
.collect::<anyhow::Result<Api>>()?;
};

result.merge(api)
})?;

match args.command {
Command::Generate {
Expand Down