summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyborus <cyborus@cyborus.xyz>2024-01-16 20:01:37 +0100
committerCyborus <cyborus@cyborus.xyz>2024-01-16 20:01:37 +0100
commitf30b4eba308bf782eba96aae48adb63c8fd8fbca (patch)
treea3dd263ec2adea557eb16c99e744b1d73b3c8ab4
parentconvert path args to camel case in format string (diff)
downloadforgejo-api-f30b4eba308bf782eba96aae48adb63c8fd8fbca.tar.xz
forgejo-api-f30b4eba308bf782eba96aae48adb63c8fd8fbca.zip
autogenerate structs
-rw-r--r--generator/src/main.rs60
1 files changed, 58 insertions, 2 deletions
diff --git a/generator/src/main.rs b/generator/src/main.rs
index 23a8bd0..04a3ede 100644
--- a/generator/src/main.rs
+++ b/generator/src/main.rs
@@ -18,7 +18,14 @@ fn main() -> eyre::Result<()> {
for (path, item) in &spec.paths {
s.push_str(&create_methods_for_path(&spec, path, item).wrap_err_with(|| path.clone())?);
}
- s.push('}');
+ s.push_str("}\n");
+
+ if let Some(definitions) = &spec.definitions {
+ for (name, schema) in definitions {
+ let strukt = create_struct_for_definition(&spec, name, schema)?;
+ s.push_str(&strukt);
+ }
+ }
save_generated(&mut s)?;
Ok(())
}
@@ -575,10 +582,59 @@ fn sanitize_ident(mut s: String) -> String {
"as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn",
"for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
"return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe",
- "use", "where", "while",
+ "use", "where", "while", "abstract", "become", "box", "do", "final", "macro", "override",
+ "priv", "typeof", "unsized", "virtual", "yield", "async", "await", "dyn", "try",
+ "macro_rules", "union"
];
+ if s == "self" {
+ s = "this".into();
+ }
if keywords.contains(&&*s) {
s.insert_str(0, "r#");
}
s
}
+
+fn create_struct_for_definition(spec: &OpenApiV2, name: &str, schema: &Schema) -> eyre::Result<String> {
+ if matches!(schema._type, Some(SchemaType::One(Primitive::Array))) {
+ return Ok(String::new());
+ }
+
+ let docs = create_struct_docs(schema)?;
+ let mut fields = String::new();
+ let required = schema.required.as_deref().unwrap_or_default();
+ if let Some(properties) = &schema.properties {
+ for (prop_name, prop_schema) in properties {
+ let prop_ty = schema_ref_type_name(spec, prop_schema)?;
+ let field_name = sanitize_ident(prop_name.to_snake_case());
+ let field_ty = if required.contains(prop_name) {
+ prop_ty
+ } else {
+ format!("Option<{prop_ty}>")
+ };
+ fields.push_str(&field_name);
+ fields.push_str(": ");
+ fields.push_str(&field_ty);
+ fields.push_str(",\n");
+ }
+ }
+
+ let out = format!("{docs}pub struct {name} {{\n{fields}}}\n\n");
+ Ok(out)
+}
+
+fn create_struct_docs(schema: &Schema) -> eyre::Result<String> {
+ let doc = match &schema.description {
+ Some(desc) => {
+ let mut out = String::new();
+ for line in desc.lines() {
+ out.push_str("/// ");
+ out.push_str(line);
+ out.push_str("\n/// \n");
+ }
+ out
+ },
+ None => String::new(),
+ };
+ Ok(doc)
+}