Skip to content

Commit 9a2a810

Browse files
committed
Allow import/export in toml for pmrctrl.
1 parent 24cb9c8 commit 9a2a810

File tree

3 files changed

+70
-10
lines changed

3 files changed

+70
-10
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ test-binary = "3.0.2"
9595
textwrap-macros = "0.3.0"
9696
thiserror = "1.0"
9797
time = "0.3.36"
98+
toml = "0.9.5"
9899
tokio = "1.35"
99100
tokio-stream = "0.1.5"
100101
tokio-util = "0.7.11"

pmrctrl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ serde_json = { workspace = true }
2323
stderrlog = { workspace = true }
2424
thiserror = { workspace = true }
2525
tokio = { workspace = true, features = ["sync", "fs"] }
26+
toml = { workspace = true }
2627

2728
[dev-dependencies]
2829
anyhow = { workspace = true }

pmrctrl/src/bin/pmrctrl.rs

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clap::{
22
Parser,
33
Subcommand,
4+
ValueEnum,
45
};
56
use pmrcore::{
67
exposure::{
@@ -43,18 +44,70 @@ use std::{
4344
stdin,
4445
BufReader,
4546
},
47+
sync::OnceLock,
4648
};
4749

50+
#[derive(Clone, Debug, ValueEnum)]
51+
pub enum SerdeKind {
52+
Json,
53+
Toml,
54+
}
55+
56+
mod display {
57+
use std::fmt::{Display, Formatter, Result};
58+
use super::SerdeKind;
4859

60+
impl Display for SerdeKind {
61+
fn fmt(&self, f: &mut Formatter) -> Result {
62+
match self {
63+
Self::Json => "json".fmt(f),
64+
Self::Toml => "toml".fmt(f),
65+
}
66+
}
67+
}
68+
}
69+
70+
impl SerdeKind {
71+
pub fn to_string<T>(&self, item: &T) -> Result<String, anyhow::Error>
72+
where
73+
T: serde::Serialize,
74+
{
75+
Ok(match self {
76+
Self::Json => serde_json::to_string_pretty(item)?,
77+
Self::Toml => toml::to_string(item)?,
78+
})
79+
}
80+
81+
pub fn from_reader<R, T>(&self, rdr: R) -> Result<T, anyhow::Error>
82+
where
83+
R: std::io::Read,
84+
T: serde::de::DeserializeOwned,
85+
{
86+
Ok(match self {
87+
Self::Json => serde_json::from_reader(rdr)?,
88+
Self::Toml => toml::from_slice(&rdr.bytes().collect::<Result<Vec<_>, _>>()?)?,
89+
})
90+
}
91+
}
92+
93+
#[derive(Debug, Parser)]
94+
struct Config {
95+
#[clap(short = 'o', long = "format", default_value_t = SerdeKind::Json)]
96+
serde_kind: SerdeKind,
97+
#[clap(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
98+
verbose: u8,
99+
}
100+
101+
static CONF: OnceLock<Config> = OnceLock::new();
49102

50103
#[derive(Debug, Parser)]
51104
struct Cli {
52105
#[command(subcommand)]
53106
command: Commands,
54107
#[clap(flatten)]
55108
platform_builder: PlatformBuilder,
56-
#[clap(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
57-
verbose: u8,
109+
#[clap(flatten)]
110+
config: Config,
58111
}
59112

60113

@@ -239,7 +292,7 @@ async fn main() -> anyhow::Result<()> {
239292
.module(module_path!())
240293
.module("pmrdb")
241294
.module("pmrtqs")
242-
.verbosity((args.verbose as usize) + 1)
295+
.verbosity((args.config.verbose as usize) + 1)
243296
.timestamp(stderrlog::Timestamp::Second)
244297
.init()
245298
.unwrap();
@@ -249,6 +302,8 @@ async fn main() -> anyhow::Result<()> {
249302
.await
250303
.map_err(anyhow::Error::from_boxed)?;
251304

305+
let _ = CONF.set(args.config);
306+
252307
match args.command {
253308
Commands::Alias { cmd } => {
254309
parse_alias(&platform, cmd).await?;
@@ -353,6 +408,7 @@ async fn parse_profile<'p>(
353408
platform: &'p Platform,
354409
arg: ProfileCmd,
355410
) -> anyhow::Result<()> {
411+
let conf = CONF.get().expect("config is set by main");
356412
match arg {
357413
ProfileCmd::Create { title, description } => {
358414
let id = ProfileBackend::insert_profile(
@@ -378,9 +434,9 @@ async fn parse_profile<'p>(
378434
let cache = ChoiceRegistryCache::from(
379435
&registry as &dyn ChoiceRegistry<_>);
380436
let uvpr: UserViewProfileRef = (&result, &cache).into();
381-
serde_json::to_string_pretty(&uvpr)?
437+
conf.serde_kind.to_string(&uvpr)?
382438
} else {
383-
serde_json::to_string_pretty(&result)?
439+
conf.serde_kind.to_string(&result)?
384440
};
385441
println!("{output}");
386442
},
@@ -431,12 +487,13 @@ async fn parse_vtt<'p>(
431487
platform: &'p Platform,
432488
arg: VttCmd,
433489
) -> anyhow::Result<()> {
490+
let conf = CONF.get().expect("config is set by main");
434491
match arg {
435492
VttCmd::Import { input } => {
436493
let id = platform.adds_view_task_template(
437494
match input {
438-
Some(path) => serde_json::from_reader(BufReader::new(fs::File::open(path)?))?,
439-
None => serde_json::from_reader(BufReader::new(stdin()))?,
495+
Some(path) => conf.serde_kind.from_reader(BufReader::new(fs::File::open(path)?))?,
496+
None => conf.serde_kind.from_reader(BufReader::new(stdin()))?,
440497
}
441498
).await?;
442499
println!("imported ViewTaskTemplate {id}");
@@ -455,7 +512,7 @@ async fn parse_vtt<'p>(
455512
}
456513
VttCmd::Export { id } => {
457514
let result = platform.get_view_task_template(id).await?;
458-
let output = serde_json::to_string_pretty(&result)?;
515+
let output = conf.serde_kind.to_string(&result)?;
459516
println!("{output}");
460517
}
461518
}
@@ -496,6 +553,7 @@ async fn parse_exposure_path<'p>(
496553
) -> anyhow::Result<()> {
497554
let ec = platform.get_exposure(exposure_id).await?;
498555
let efc = ec.ctrl_path(path).await?;
556+
let conf = CONF.get().expect("config is set by main");
499557
match arg {
500558
ExposurePathCmd::Assign { profile_id } => {
501559
let exposure_file_id = efc.exposure_file().id();
@@ -506,7 +564,7 @@ async fn parse_exposure_path<'p>(
506564
ExposurePathCmd::Prompts => {
507565
let efvttsc = efc.build_vttc().await?;
508566
let upgr = efvttsc.create_user_prompt_groups()?;
509-
let output = serde_json::to_string_pretty(&upgr)?;
567+
let output = conf.serde_kind.to_string(&upgr)?;
510568
println!("{output}");
511569
},
512570
ExposurePathCmd::Answer { arg_id, answer } => {
@@ -583,7 +641,7 @@ async fn parse_exposure_path<'p>(
583641
efc.process_vttc_tasks(vttc_tasks).await?;
584642
println!("{len} task(s) queued");
585643
} else {
586-
let output = serde_json::to_string_pretty(&vttc_tasks)?;
644+
let output = conf.serde_kind.to_string(&vttc_tasks)?;
587645
println!("The generated VTTCTasks:");
588646
println!("{output}");
589647
};

0 commit comments

Comments
 (0)