1use std::{borrow::Cow, collections::BTreeSet, fmt::Display};
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
7pub enum ProjectSelector {
8 All,
9 #[serde(untagged)]
10 Array(BTreeSet<String>),
11 #[serde(untagged)]
12 IncludeExclude {
13 include: BTreeSet<String>,
14 exclude: BTreeSet<String>,
15 },
16 #[serde(untagged)]
17 Tagged(BTreeSet<String>),
18}
19
20impl Display for ProjectSelector {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 f.write_str(&match self {
23 Self::All => Cow::Borrowed("all projects"),
24 Self::Array(names) => format!("projects with names: {names:?}").into(),
25 Self::IncludeExclude { include, exclude } => {
26 format!("projects matching expressions {include:?}, excluding {exclude:?}").into()
27 }
28 Self::Tagged(tags) => format!("projects tagged with: {tags:?}").into(),
29 })
30 }
31}
32
33impl ProjectSelector {
34 pub fn all() -> Self {
35 Self::All
36 }
37
38 pub fn array<N: IntoIterator<Item = S>, S: AsRef<str>>(names: N) -> Self {
39 Self::Array(names.into_iter().map(|name| name.as_ref().into()).collect())
40 }
41
42 pub fn include_exclude<S: AsRef<str>, I: IntoIterator<Item = S>, E: IntoIterator<Item = S>>(
43 include: I,
44 exclude: E,
45 ) -> Self {
46 Self::IncludeExclude {
47 include: include
48 .into_iter()
49 .map(|pattern| pattern.as_ref().into())
50 .collect(),
51 exclude: exclude
52 .into_iter()
53 .map(|pattern| pattern.as_ref().into())
54 .collect(),
55 }
56 }
57
58 pub fn tagged<S: AsRef<str>, I: IntoIterator<Item = S>>(tags: I) -> Self {
59 Self::Tagged(tags.into_iter().map(|s| s.as_ref().to_owned()).collect())
60 }
61}