reactive_graph_command_model/entity/
arg.rs1use clap::Arg;
2use serde::Deserialize;
3use serde::Serialize;
4use serde_json::Value;
5
6use crate::error::CommandArgsError;
7use crate::error::InvalidCommandArgDefinition;
8use reactive_graph_graph::DataType;
9use reactive_graph_graph::PropertyType;
10use reactive_graph_graph::PropertyTypes;
11use reactive_graph_graph::SocketType;
12
13#[derive(Serialize, Deserialize, Debug, Clone)]
14pub struct CommandArg {
15 pub name: String,
18
19 pub short: Option<char>,
22
23 pub long: Option<String>,
26
27 pub help: Option<String>,
29
30 #[serde(default = "bool::default")]
32 pub required: bool,
33}
34
35impl CommandArg {
36 pub fn new<S: Into<String>>(name: S) -> Self {
37 Self {
38 name: name.into(),
39 short: None,
40 long: None,
41 help: None,
42 required: false,
43 }
44 }
45
46 pub fn short(self, short: char) -> Self {
47 Self {
48 name: self.name,
49 short: Some(short),
50 long: self.long,
51 help: self.help,
52 required: self.required,
53 }
54 }
55
56 pub fn long<S: Into<String>>(self, long: S) -> Self {
57 Self {
58 name: self.name,
59 short: self.short,
60 long: Some(long.into()),
61 help: None,
62 required: self.required,
63 }
64 }
65
66 pub fn help<S: Into<String>>(self, help: S) -> Self {
67 Self {
68 name: self.name,
69 short: self.short,
70 long: self.long,
71 help: Some(help.into()),
72 required: self.required,
73 }
74 }
75
76 pub fn required(self, required: bool) -> Self {
77 Self {
78 name: self.name,
79 short: self.short,
80 long: self.long,
81 help: self.help,
82 required,
83 }
84 }
85
86 pub fn as_arg(&self) -> Arg {
87 let mut arg = Arg::new(self.name.clone());
88 if let Some(long) = &self.long {
89 arg = arg.long(long.clone());
90 }
91 if let Some(help) = self.help.clone() {
92 arg = arg.help(help);
93 }
94 arg
95 }
96}
97
98impl TryFrom<Value> for CommandArg {
99 type Error = InvalidCommandArgDefinition;
100
101 fn try_from(value: Value) -> Result<Self, Self::Error> {
102 let arg: CommandArg = serde_json::from_value(value).map_err(InvalidCommandArgDefinition)?;
103 Ok(arg)
104 }
105}
106
107impl From<String> for CommandArg {
108 fn from(name: String) -> Self {
109 CommandArg::new(name)
110 }
111}
112
113impl From<&str> for CommandArg {
114 fn from(name: &str) -> Self {
115 CommandArg::new(name)
116 }
117}
118
119impl From<CommandArg> for PropertyType {
120 fn from(arg: CommandArg) -> Self {
121 PropertyType::builder()
122 .name(arg.name)
123 .description(arg.help.unwrap_or_default())
124 .data_type(DataType::Any)
125 .socket_type(SocketType::Input)
126 .build()
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct CommandArgs(Vec<CommandArg>);
132
133impl CommandArgs {
134 pub fn new() -> Self {
135 CommandArgs(Vec::new())
136 }
137
138 pub fn arg<A: Into<CommandArg>>(mut self, arg: A) -> Self {
139 self.0.push(arg.into());
140 self
141 }
142
143 pub fn push(&mut self, arg: CommandArg) {
144 self.0.push(arg);
145 }
146
147 pub fn contains<S: Into<String>>(&self, name: S) -> bool {
148 let name = name.into();
149 self.0.iter().any(|arg| arg.name == name)
150 }
151
152 pub fn len(&self) -> usize {
153 self.0.len()
154 }
155
156 pub fn is_empty(&self) -> bool {
157 self.len() == 0
158 }
159
160 pub fn to_value(&self) -> Value {
161 Value::Array(self.0.iter().filter_map(|arg| serde_json::to_value(arg).ok()).collect())
162 }
163
164 pub fn as_args(&self) -> Vec<Arg> {
165 self.0.iter().map(|arg| arg.as_arg()).collect()
166 }
167
168 pub fn to_vec(&self) -> Vec<CommandArg> {
169 self.0.to_vec()
170 }
171
172 pub fn to_property_types(&self) -> PropertyTypes {
173 self.to_vec().iter().map(|arg| arg.clone().into()).collect::<Vec<_>>().into()
174 }
175}
176
177impl Default for CommandArgs {
178 fn default() -> Self {
179 Self::new()
180 }
181}
182
183impl TryFrom<Value> for CommandArgs {
184 type Error = CommandArgsError;
185
186 fn try_from(args: Value) -> Result<Self, Self::Error> {
187 args.as_array()
188 .map(|args| {
189 match args.iter().map(|arg| CommandArg::try_from(arg.clone())).collect() {
191 Ok(args) => Ok(CommandArgs(args)),
192 Err(e) => Err(CommandArgsError::InvalidCommandArgDefinition(e)),
193 }
194 })
195 .unwrap_or(Err(CommandArgsError::CommandArgDefinitionMissing))
196 }
197}