use std::fmt::Write;
use anyhow::{Context, Result};
use structopt::StructOpt;
use crate::schema::SqlType;
#[derive(Debug, StructOpt)]
pub struct Options {
#[structopt(short = "U", default_value = "localhost:8123")]
pub url: String,
#[structopt(short = "u")]
pub user: Option<String>,
#[structopt(short = "p")]
pub password: Option<String>,
#[structopt(short = "d", default_value = "default")]
pub database: String,
pub table: String,
#[structopt(short = "S")]
pub serialize: bool,
#[structopt(short = "D")]
pub deserialize: bool,
#[structopt(long)]
pub owned: bool,
#[structopt(short = "T", parse(try_from_str = parse_type), number_of_values = 1)]
pub types: Vec<Type>,
#[structopt(short = "O", parse(try_from_str = parse_override), number_of_values = 1)]
pub overrides: Vec<Override>,
#[structopt(short = "B")]
pub bytes: Vec<String>,
#[structopt(short = "I", number_of_values = 1)]
pub ignore: Vec<String>,
#[structopt(long = "derive", number_of_values = 1, name = "trait")]
pub derives: Vec<String>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Type {
pub sql: SqlType,
pub type_: String,
}
fn parse_type(s: &str) -> Result<Type> {
let (sql, type_) = s.split_once('=').context("invalid key-value")?;
Ok(Type {
sql: crate::miner::parse_type(sql)?,
type_: type_.into(),
})
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Override {
pub column: String,
pub type_: String,
}
fn parse_override(s: &str) -> Result<Override> {
let (column, type_) = s.split_once('=').context("invalid key-value")?;
Ok(Override {
column: column.into(),
type_: type_.into(),
})
}
impl Options {
pub fn format(&self) -> String {
let mut s = String::new();
let _ = write!(&mut s, "ch2rs {}", self.table);
if self.database != "default" {
let _ = write!(&mut s, " -d {}", self.database);
}
if self.serialize {
s.push_str(" -S");
}
if self.deserialize {
s.push_str(" -D");
}
if self.owned {
s.push_str(" --owned");
}
s.push_str(" \\\n");
if !self.derives.is_empty() {
for derive in &self.derives {
s.push_str(" --derive ");
s.push_str(derive);
s.push_str(" \\\n");
}
}
let mut types = self.types.iter().collect::<Vec<_>>();
types.sort();
for t in types {
let _ = writeln!(&mut s, " -T '{}={}' \\", t.sql, t.type_);
}
let mut overrides = self.overrides.iter().collect::<Vec<_>>();
overrides.sort();
for o in overrides {
let _ = writeln!(&mut s, " -O '{}={}' \\", o.column, o.type_);
}
let mut bytes = self.bytes.iter().collect::<Vec<_>>();
bytes.sort();
for b in bytes {
let _ = writeln!(&mut s, " -B '{}' \\", b);
}
let mut ignore = self.ignore.iter().collect::<Vec<_>>();
ignore.sort();
for i in ignore {
let _ = writeln!(&mut s, " -I '{}' \\", i);
}
s.trim_end_matches(|c| c == '\\' || c == ' ' || c == '\n')
.into()
}
}