1use crate::ResetData;
2use std::num::NonZeroUsize;
3use std::path::PathBuf;
4
5use crate::NonZeroDecimal;
6use clap::Parser;
7
8use crate::FPS;
9
10#[derive(Debug, Parser)]
11pub struct Cli {
12 #[arg(value_parser=is_file)]
14 pub input: PathBuf,
15
16 #[arg(value_parser=output_dne)]
19 pub output: PathBuf,
20 #[arg(value_parser=is_file, env)]
23 pub ai_binary: PathBuf,
24
25 #[arg(value_parser=is_dir, env)]
26 pub ai_model: PathBuf,
27
28 #[arg(long, value_enum, default_value_t=FPS::default())]
32 pub fps: FPS,
33
34 #[arg(short, value_parser=dne_or_is_dir)]
39 pub temp_dir: PathBuf,
40
41 #[arg(short='m', default_value_t = NonZeroUsize::new(50).unwrap())]
43 pub max_step_size: NonZeroUsize,
44
45 #[arg(long, default_value_t = default_ai_args())]
47 pub ai_args: String,
48
49 #[arg(short='r', default_value_t = ResetData::default())]
51 pub reset: ResetData,
52
53 #[arg(short='s', default_value_t = String::from(".1"), value_parser=can_be_decimal)]
57 pub scene_gt: String,
58
59 #[arg(long, default_value_t = NonZeroUsize::new(18).unwrap())]
61 pub crf: NonZeroUsize,
62}
63
64fn can_be_decimal(scene_gt: &str) -> Result<String, String> {
65 NonZeroDecimal::try_from(scene_gt)
66 .map_err(|e| format!("scene_gt should be a non-zero decimal: {e}"))?;
67 Ok(scene_gt.to_owned())
68}
69
70fn is_file(path: &str) -> Result<PathBuf, String> {
72 let path = PathBuf::from(path);
73 if !path.is_file() {
74 return Err(format!("path doesn't exist or isn't a file: {path:?}"));
75 }
76 Ok(path)
77}
78
79fn is_dir(path: &str) -> Result<PathBuf, String> {
80 let path = PathBuf::from(path);
81 if !path.is_dir() {
82 return Err(format!("path doesn't exist is isn't a directory: {path:?}"));
83 }
84 Ok(path)
85}
86
87fn dne_or_is_dir(path: &str) -> Result<PathBuf, String> {
88 let path = PathBuf::from(path);
89 if path.exists() && !path.is_dir() {
90 return Err(format!(
91 "Path should not exist or should be a folder: {path:?}"
92 ));
93 }
94 Ok(path)
95}
96
97fn output_dne(path: &str) -> Result<PathBuf, String> {
98 let path = PathBuf::from(path);
99 if path.exists() {
100 return Err(format!(
101 "Output path already exist. Please delete the file to continue: {path:?}"
102 ));
103 }
104 Ok(path)
105}
106
107fn default_ai_args() -> String {
108 let cpu_count = num_cpus::get();
109 format!("-g 0,-1 -j {cpu_count}:{cpu_count},16:32:16")
110}