1use anyhow::Result;
18use clap::Args;
19use std::{
20 convert::TryFrom,
21 fmt,
22};
23
24#[derive(Default, Clone, Debug, Args)]
25pub struct VerbosityFlags {
26 #[clap(long)]
28 quiet: bool,
29 #[clap(long)]
31 verbose: bool,
32}
33
34impl TryFrom<&VerbosityFlags> for Verbosity {
35 type Error = anyhow::Error;
36
37 fn try_from(value: &VerbosityFlags) -> Result<Self, Self::Error> {
38 match (value.quiet, value.verbose) {
39 (false, false) => Ok(Verbosity::Default),
40 (true, false) => Ok(Verbosity::Quiet),
41 (false, true) => Ok(Verbosity::Verbose),
42 (true, true) => anyhow::bail!("Cannot pass both --quiet and --verbose flags"),
43 }
44 }
45}
46
47#[derive(
49 Clone, Copy, Default, serde::Serialize, serde::Deserialize, Eq, PartialEq, Debug,
50)]
51pub enum Verbosity {
52 #[default]
54 Default,
55 Quiet,
57 Verbose,
59}
60
61impl Verbosity {
62 pub fn is_verbose(&self) -> bool {
64 match self {
65 Verbosity::Quiet => false,
66 Verbosity::Default | Verbosity::Verbose => true,
67 }
68 }
69}
70
71#[derive(Eq, PartialEq, Copy, Clone, Debug, Default, serde::Serialize)]
74pub enum Network {
75 #[default]
77 Online,
78 Offline,
80}
81
82impl Network {
83 pub fn append_to_args(&self, args: &mut Vec<String>) {
85 match self {
86 Self::Online => (),
87 Self::Offline => args.push("--offline".to_owned()),
88 }
89 }
90}
91
92#[derive(
94 Copy,
95 Clone,
96 Default,
97 Eq,
98 PartialEq,
99 Debug,
100 clap::ValueEnum,
101 serde::Serialize,
102 serde::Deserialize,
103)]
104#[clap(name = "build-artifacts")]
105pub enum BuildArtifacts {
106 #[clap(name = "all")]
108 #[default]
109 All,
110 #[clap(name = "code-only")]
113 CodeOnly,
114 #[clap(name = "check-only")]
117 CheckOnly,
118}
119
120impl BuildArtifacts {
121 pub fn steps(&self) -> usize {
124 match self {
125 BuildArtifacts::All => 5,
126 BuildArtifacts::CodeOnly => 4,
127 BuildArtifacts::CheckOnly => 1,
128 }
129 }
130}
131
132#[derive(
134 Eq,
135 PartialEq,
136 Copy,
137 Clone,
138 Debug,
139 Default,
140 clap::ValueEnum,
141 serde::Serialize,
142 serde::Deserialize,
143 strum::EnumIter,
144)]
145pub enum Target {
146 #[clap(name = "wasm")]
148 #[default]
149 Wasm,
150 #[clap(name = "riscv")]
152 RiscV,
153}
154
155impl Target {
156 pub fn llvm_target(&self) -> &'static str {
158 match self {
159 Self::Wasm => "wasm32-unknown-unknown",
160 Self::RiscV => "riscv32i-unknown-none-elf",
161 }
162 }
163
164 pub fn rustflags(&self) -> Option<&'static str> {
166 match self {
167 Self::Wasm => Some("-Clink-arg=-zstack-size=65536\x1f-Clink-arg=--import-memory\x1f-Ctarget-cpu=mvp"),
168 Self::RiscV => None,
169 }
170 }
171
172 pub fn source_extension(&self) -> &'static str {
174 match self {
175 Self::Wasm => "wasm",
176 Self::RiscV => "",
177 }
178 }
179
180 pub fn dest_extension(&self) -> &'static str {
182 match self {
183 Self::Wasm => "wasm",
184 Self::RiscV => "riscv",
185 }
186 }
187}
188
189#[derive(
191 Eq, PartialEq, Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize,
192)]
193pub enum BuildMode {
194 #[default]
196 Debug,
197 Release,
199 Verifiable,
201}
202
203impl fmt::Display for BuildMode {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 match self {
206 Self::Debug => write!(f, "debug"),
207 Self::Release => write!(f, "release"),
208 Self::Verifiable => write!(f, "verifiable"),
209 }
210 }
211}
212
213#[derive(Clone, Debug, Default)]
215pub enum OutputType {
216 #[default]
218 HumanReadable,
219 Json,
221}
222
223#[derive(Default, Clone, Debug, Args)]
224pub struct UnstableOptions {
225 #[clap(long = "unstable-options", short = 'Z', number_of_values = 1)]
227 options: Vec<String>,
228}
229
230#[derive(Clone, Default)]
231pub struct UnstableFlags {
232 pub original_manifest: bool,
233}
234
235impl TryFrom<&UnstableOptions> for UnstableFlags {
236 type Error = anyhow::Error;
237
238 fn try_from(value: &UnstableOptions) -> Result<Self, Self::Error> {
239 let valid_flags = ["original-manifest"];
240 let invalid_flags = value
241 .options
242 .iter()
243 .filter(|o| !valid_flags.contains(&o.as_str()))
244 .collect::<Vec<_>>();
245 if !invalid_flags.is_empty() {
246 anyhow::bail!("Unknown unstable-options {:?}", invalid_flags)
247 }
248 Ok(UnstableFlags {
249 original_manifest: value.options.contains(&"original-manifest".to_owned()),
250 })
251 }
252}
253
254#[derive(Default, Clone, Debug, Args)]
256pub struct Features {
257 #[clap(long, value_delimiter = ',')]
259 features: Vec<String>,
260}
261
262impl Features {
263 pub fn push(&mut self, feature: &str) {
265 self.features.push(feature.to_owned())
266 }
267
268 pub fn append_to_args(&self, args: &mut Vec<String>) {
270 if !self.features.is_empty() {
271 args.push("--features".to_string());
272 let features = if self.features.len() == 1 {
273 self.features[0].clone()
274 } else {
275 self.features.join(",")
276 };
277 args.push(features);
278 }
279 }
280}