2022-08-29 18:16:34 +00:00
|
|
|
// Copyright 2022 Oxide Computer Company
|
2021-10-17 17:40:22 +00:00
|
|
|
|
|
|
|
use std::{
|
|
|
|
fs::{File, OpenOptions},
|
|
|
|
io::Write,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
};
|
|
|
|
|
|
|
|
use anyhow::{bail, Result};
|
2022-07-03 02:09:38 +00:00
|
|
|
use clap::{Parser, ValueEnum};
|
2021-10-17 17:40:22 +00:00
|
|
|
use openapiv3::OpenAPI;
|
2022-07-03 02:09:38 +00:00
|
|
|
use progenitor::{GenerationSettings, Generator, InterfaceStyle, TagStyle};
|
2021-10-17 17:40:22 +00:00
|
|
|
|
2022-07-03 02:09:38 +00:00
|
|
|
#[derive(Parser)]
|
|
|
|
struct Args {
|
2023-01-14 16:58:57 +00:00
|
|
|
/// OpenAPI definition document (JSON or YAML)
|
2022-07-03 02:09:38 +00:00
|
|
|
#[clap(short = 'i', long)]
|
|
|
|
input: String,
|
|
|
|
/// Output directory for Rust crate
|
|
|
|
#[clap(short = 'o', long)]
|
|
|
|
output: String,
|
|
|
|
/// Target Rust crate name
|
|
|
|
#[clap(short = 'n', long)]
|
|
|
|
name: String,
|
|
|
|
/// Target Rust crate version
|
|
|
|
#[clap(short = 'v', long)]
|
|
|
|
version: String,
|
|
|
|
|
|
|
|
/// SDK interface style
|
|
|
|
#[clap(value_enum, long, default_value_t = InterfaceArg::Positional)]
|
|
|
|
interface: InterfaceArg,
|
|
|
|
/// SDK tag style
|
|
|
|
#[clap(value_enum, long, default_value_t = TagArg::Merged)]
|
|
|
|
tags: TagArg,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, ValueEnum)]
|
|
|
|
enum InterfaceArg {
|
|
|
|
Positional,
|
|
|
|
Builder,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<InterfaceArg> for InterfaceStyle {
|
|
|
|
fn from(arg: InterfaceArg) -> Self {
|
|
|
|
match arg {
|
|
|
|
InterfaceArg::Positional => InterfaceStyle::Positional,
|
|
|
|
InterfaceArg::Builder => InterfaceStyle::Builder,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, ValueEnum)]
|
|
|
|
enum TagArg {
|
|
|
|
Merged,
|
|
|
|
Separate,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<TagArg> for TagStyle {
|
|
|
|
fn from(arg: TagArg) -> Self {
|
|
|
|
match arg {
|
|
|
|
TagArg::Merged => TagStyle::Merged,
|
|
|
|
TagArg::Separate => TagStyle::Separate,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:40:22 +00:00
|
|
|
fn save<P>(p: P, data: &str) -> Result<()>
|
|
|
|
where
|
|
|
|
P: AsRef<Path>,
|
|
|
|
{
|
|
|
|
let p = p.as_ref();
|
|
|
|
let mut f = OpenOptions::new()
|
|
|
|
.create(true)
|
|
|
|
.truncate(true)
|
|
|
|
.write(true)
|
|
|
|
.open(p)?;
|
|
|
|
f.write_all(data.as_bytes())?;
|
|
|
|
f.flush()?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() -> Result<()> {
|
2022-07-03 02:09:38 +00:00
|
|
|
let args = Args::parse();
|
|
|
|
let api = load_api(&args.input)?;
|
2021-10-17 17:40:22 +00:00
|
|
|
|
2022-07-03 02:09:38 +00:00
|
|
|
let mut builder = Generator::new(
|
|
|
|
GenerationSettings::default()
|
|
|
|
.with_interface(args.interface.into())
|
|
|
|
.with_tag(args.tags.into()),
|
|
|
|
);
|
2021-10-17 17:40:22 +00:00
|
|
|
|
2022-02-08 16:59:38 +00:00
|
|
|
match builder.generate_text(&api) {
|
|
|
|
Ok(api_code) => {
|
2021-10-17 17:40:22 +00:00
|
|
|
let type_space = builder.get_type_space();
|
|
|
|
|
|
|
|
println!("-----------------------------------------------------");
|
|
|
|
println!(" TYPE SPACE");
|
|
|
|
println!("-----------------------------------------------------");
|
|
|
|
for (idx, type_entry) in type_space.iter_types().enumerate() {
|
|
|
|
let n = type_entry.describe();
|
|
|
|
println!("{:>4} {}", idx, n);
|
|
|
|
}
|
|
|
|
println!("-----------------------------------------------------");
|
|
|
|
println!();
|
|
|
|
|
2022-07-03 02:09:38 +00:00
|
|
|
let name = &args.name;
|
|
|
|
let version = &args.version;
|
2021-10-17 17:40:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the top-level crate directory:
|
|
|
|
*/
|
2022-07-03 02:09:38 +00:00
|
|
|
let root = PathBuf::from(&args.output);
|
2021-10-17 17:40:22 +00:00
|
|
|
std::fs::create_dir_all(&root)?;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write the Cargo.toml file:
|
|
|
|
*/
|
|
|
|
let mut toml = root.clone();
|
|
|
|
toml.push("Cargo.toml");
|
|
|
|
|
|
|
|
let tomlout = format!(
|
|
|
|
"[package]\n\
|
|
|
|
name = \"{}\"\n\
|
|
|
|
version = \"{}\"\n\
|
2022-08-29 18:16:34 +00:00
|
|
|
edition = \"2021\"\n\
|
2021-10-17 17:40:22 +00:00
|
|
|
\n\
|
|
|
|
[dependencies]\n\
|
2022-02-08 16:59:38 +00:00
|
|
|
{}\n\
|
2022-07-15 02:36:09 +00:00
|
|
|
\n",
|
2021-10-17 17:40:22 +00:00
|
|
|
name,
|
|
|
|
version,
|
|
|
|
builder.dependencies().join("\n"),
|
|
|
|
);
|
|
|
|
|
|
|
|
save(&toml, tomlout.as_str())?;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the src/ directory:
|
|
|
|
*/
|
|
|
|
let mut src = root;
|
|
|
|
src.push("src");
|
|
|
|
std::fs::create_dir_all(&src)?;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the Rust source file containing the generated client:
|
|
|
|
*/
|
2022-02-08 16:59:38 +00:00
|
|
|
let lib_code = format!("mod progenitor_client;\n\n{}", api_code);
|
|
|
|
let mut librs = src.clone();
|
2021-10-17 17:40:22 +00:00
|
|
|
librs.push("lib.rs");
|
2022-02-08 16:59:38 +00:00
|
|
|
save(librs, lib_code.as_str())?;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the Rust source file containing the support code:
|
|
|
|
*/
|
2022-05-13 17:26:22 +00:00
|
|
|
let progenitor_client_code = progenitor_client::code();
|
2022-02-08 16:59:38 +00:00
|
|
|
let mut clientrs = src;
|
|
|
|
clientrs.push("progenitor_client.rs");
|
|
|
|
save(clientrs, progenitor_client_code)?;
|
2021-10-17 17:40:22 +00:00
|
|
|
}
|
2022-02-08 16:59:38 +00:00
|
|
|
|
2021-10-17 17:40:22 +00:00
|
|
|
Err(e) => {
|
|
|
|
println!("gen fail: {:?}", e);
|
2022-02-08 16:59:38 +00:00
|
|
|
bail!("generation experienced errors");
|
2021-10-17 17:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-01-14 16:58:57 +00:00
|
|
|
fn load_api<P>(p: P) -> Result<OpenAPI>
|
2021-10-17 17:40:22 +00:00
|
|
|
where
|
2023-01-14 16:58:57 +00:00
|
|
|
P: AsRef<Path> + std::clone::Clone + std::fmt::Debug,
|
2021-10-17 17:40:22 +00:00
|
|
|
{
|
2023-01-14 16:58:57 +00:00
|
|
|
let mut f = File::open(p.clone())?;
|
|
|
|
let api = match serde_json::from_reader(f) {
|
|
|
|
Ok(json_value) => json_value,
|
|
|
|
_ => {
|
|
|
|
f = File::open(p)?;
|
|
|
|
serde_yaml::from_reader(f)?
|
|
|
|
}
|
|
|
|
};
|
2021-10-17 17:40:22 +00:00
|
|
|
Ok(api)
|
|
|
|
}
|