uv_configuration/
name_specifiers.rs1#[cfg(feature = "schemars")]
2use std::borrow::Cow;
3use std::str::FromStr;
4
5use uv_normalize::PackageName;
6
7#[derive(Debug, Clone)]
11pub enum PackageNameSpecifier {
12 All,
13 None,
14 Package(PackageName),
15}
16
17impl FromStr for PackageNameSpecifier {
18 type Err = uv_normalize::InvalidNameError;
19
20 fn from_str(name: &str) -> Result<Self, Self::Err> {
21 match name {
22 ":all:" => Ok(Self::All),
23 ":none:" => Ok(Self::None),
24 _ => Ok(Self::Package(PackageName::from_str(name)?)),
25 }
26 }
27}
28
29impl<'de> serde::Deserialize<'de> for PackageNameSpecifier {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: serde::Deserializer<'de>,
33 {
34 struct Visitor;
35
36 impl serde::de::Visitor<'_> for Visitor {
37 type Value = PackageNameSpecifier;
38
39 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
40 formatter.write_str("a package name or `:all:` or `:none:`")
41 }
42
43 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
44 where
45 E: serde::de::Error,
46 {
47 match value {
49 ":all:" => Ok(PackageNameSpecifier::All),
50 ":none:" => Ok(PackageNameSpecifier::None),
51 _ => {
52 match PackageName::from_str(value) {
54 Ok(name) => Ok(PackageNameSpecifier::Package(name)),
55 Err(err) => Err(E::custom(err)),
56 }
57 }
58 }
59 }
60 }
61
62 deserializer.deserialize_str(Visitor)
63 }
64}
65
66#[cfg(feature = "schemars")]
67impl schemars::JsonSchema for PackageNameSpecifier {
68 fn schema_name() -> Cow<'static, str> {
69 Cow::Borrowed("PackageNameSpecifier")
70 }
71
72 fn json_schema(_gen: &mut schemars::generate::SchemaGenerator) -> schemars::Schema {
73 schemars::json_schema!({
74 "type": "string",
75 "pattern": r"^(:none:|:all:|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]))$",
76 "description": "The name of a package, or `:all:` or `:none:` to select or omit all packages, respectively.",
77 })
78 }
79}
80
81#[derive(Debug, Clone)]
85pub enum PackageNameSpecifiers {
86 All,
87 None,
88 Packages(Vec<PackageName>),
89}
90
91impl PackageNameSpecifiers {
92 pub(crate) fn from_iter(specifiers: impl Iterator<Item = PackageNameSpecifier>) -> Self {
93 let mut packages = Vec::new();
94 let mut all: bool = false;
95
96 for specifier in specifiers {
97 match specifier {
98 PackageNameSpecifier::None => {
99 packages.clear();
100 all = false;
101 }
102 PackageNameSpecifier::All => {
103 all = true;
104 }
105 PackageNameSpecifier::Package(name) => {
106 packages.push(name);
107 }
108 }
109 }
110
111 if all {
112 Self::All
113 } else if packages.is_empty() {
114 Self::None
115 } else {
116 Self::Packages(packages)
117 }
118 }
119}