use std::fs::File;
use std::path::PathBuf;
use hypersonic::persistance::LedgerDir;
use hypersonic::{Articles, AuthToken, CallParams, IssueParams, Schema};
#[derive(Parser)]
pub enum Cmd {
Issue {
schema: PathBuf,
params: PathBuf,
output: Option<PathBuf>,
},
Process {
articles: PathBuf,
dir: Option<PathBuf>,
},
State {
dir: PathBuf,
},
Call {
dir: PathBuf,
call: PathBuf,
},
Export {
dir: PathBuf,
#[clap(short, long)]
terminals: Vec<AuthToken>,
output: PathBuf,
},
Accept {
dir: PathBuf,
input: PathBuf,
},
}
impl Cmd {
pub fn exec(self) -> anyhow::Result<()> {
match self {
Cmd::Issue { schema, params, output } => issue(schema, params, output)?,
Cmd::Process { articles, dir } => process(articles, dir)?,
Cmd::State { dir } => state(dir)?,
Cmd::Call { dir, call: path } => call(dir, path)?,
Cmd::Export { dir, terminals, output } => export(dir, terminals, output)?,
Cmd::Accept { dir, input } => accept(dir, input)?,
}
Ok(())
}
}
fn issue(schema: PathBuf, form: PathBuf, output: Option<PathBuf>) -> anyhow::Result<()> {
let schema = Schema::load(schema)?;
let file = File::open(&form)?;
let params = serde_yaml::from_reader::<_, IssueParams>(file)?;
let path = output.unwrap_or(form);
let output = path
.with_file_name(params.name.as_str())
.with_extension("articles");
let articles = schema.issue(params);
articles.save(output)?;
Ok(())
}
fn process(articles_path: PathBuf, dir: Option<PathBuf>) -> anyhow::Result<()> {
let articles = Articles::load(&articles_path)?;
let path = dir
.or_else(|| Some(articles_path.parent()?.to_path_buf()))
.ok_or(anyhow::anyhow!("invalid path for creating the contract"))?;
LedgerDir::new(articles, path)?;
Ok(())
}
fn state(path: PathBuf) -> anyhow::Result<()> {
let ledger = LedgerDir::load(path)?;
let val = serde_yaml::to_string(&ledger.state().main)?;
println!("{val}");
Ok(())
}
fn call(dir: PathBuf, form: PathBuf) -> anyhow::Result<()> {
let mut ledger = LedgerDir::load(dir)?;
let file = File::open(form)?;
let call = serde_yaml::from_reader::<_, CallParams>(file)?;
let opid = ledger.call(call)?;
println!("Operation ID: {opid}");
Ok(())
}
fn export(dir: PathBuf, terminals: impl IntoIterator<Item = AuthToken>, output: PathBuf) -> anyhow::Result<()> {
let mut ledger = LedgerDir::load(dir)?;
ledger.export_to_file(terminals, output)?;
Ok(())
}
fn accept(dir: PathBuf, input: PathBuf) -> anyhow::Result<()> {
let mut ledger = LedgerDir::load(dir)?;
ledger.accept_from_file(input)?;
Ok(())
}