Skip to main content

nvd_cpe/
component.rs

1//! component
2use language_tags::LanguageTag;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::{convert::TryFrom, fmt, str::FromStr};
5
6use crate::error::{CPEError, Result};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
9pub enum Language {
10  // 任意值
11  #[default]
12  Any,
13  //不适用
14  NA,
15  // 解析错误
16  Value(String),
17  // 符合语言
18  Language(LanguageTag),
19}
20
21impl FromStr for Language {
22  type Err = CPEError;
23  fn from_str(s: &str) -> Result<Self> {
24    match LanguageTag::parse(s) {
25      Err(_) => match s {
26        "*" => Ok(Self::Any),
27        "-" => Ok(Self::NA),
28        _ => Ok(Self::Value(s.to_string())),
29      },
30      Ok(tag) => Ok(Self::Language(tag)),
31    }
32  }
33}
34
35impl TryFrom<&str> for Language {
36  type Error = CPEError;
37  fn try_from(val: &str) -> Result<Self> {
38    Self::from_str(val)
39  }
40}
41
42impl TryFrom<String> for Language {
43  type Error = CPEError;
44  fn try_from(val: String) -> Result<Self> {
45    Self::from_str(val.as_str())
46  }
47}
48
49impl fmt::Display for Language {
50  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51    write!(
52      f,
53      "{}",
54      match self {
55        Language::Any => "*",
56        Language::NA => "-",
57        Language::Value(s) => s.as_str(),
58        Language::Language(v) => v.as_str(),
59      }
60    )
61  }
62}
63
64impl Serialize for Language {
65  fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
66  where
67    S: Serializer,
68  {
69    serializer.serialize_str(match self {
70      Language::Any => "*",
71      Language::NA => "-",
72      Language::Value(s) => s.as_str(),
73      Language::Language(ref other) => other.as_str(),
74    })
75  }
76}
77
78impl<'de> Deserialize<'de> for Language {
79  fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
80  where
81    D: Deserializer<'de>,
82  {
83    let s = String::deserialize(deserializer)?;
84    Ok(match LanguageTag::parse(&s) {
85      Err(_) => match s.as_str() {
86        "*" => Language::Any,
87        "-" => Language::NA,
88        _ => Language::Value(s.to_string()),
89      },
90      Ok(tag) => Language::Language(tag),
91    })
92  }
93}
94// 组件
95#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
96pub enum Component {
97  // 任意值
98  #[default]
99  Any,
100  // 不适用
101  NA,
102  //组件名
103  Value(String),
104}
105
106impl Serialize for Component {
107  fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
108  where
109    S: Serializer,
110  {
111    serializer.serialize_str(match *self {
112      Component::Any => "*",
113      Component::NA => "-",
114      Component::Value(ref other) => other,
115    })
116  }
117}
118
119impl<'de> Deserialize<'de> for Component {
120  fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
121  where
122    D: Deserializer<'de>,
123  {
124    let s = String::deserialize(deserializer)?;
125    Ok(match s.as_str() {
126      "*" => Component::Any,
127      "-" => Component::NA,
128      _ => Component::Value(s),
129    })
130  }
131}
132
133impl TryFrom<&str> for Component {
134  type Error = CPEError;
135  fn try_from(val: &str) -> Result<Self> {
136    Self::from_str(val)
137  }
138}
139
140impl TryFrom<String> for Component {
141  type Error = CPEError;
142  fn try_from(val: String) -> Result<Self> {
143    Self::from_str(val.as_str())
144  }
145}
146
147impl FromStr for Component {
148  type Err = CPEError;
149
150  fn from_str(val: &str) -> Result<Self> {
151    Ok(match val {
152      "*" => Component::Any,
153      "-" => Component::NA,
154      _ => Component::Value(val.to_owned()),
155    })
156  }
157}
158
159impl Component {
160  pub fn matches(&self, val: &str) -> bool {
161    match self {
162      Component::Any => true,
163      Component::NA => false,
164      Component::Value(v) => v == val,
165    }
166  }
167
168  pub fn is_any(&self) -> bool {
169    matches!(self, Component::Any)
170  }
171
172  pub fn is_na(&self) -> bool {
173    matches!(self, Component::NA)
174  }
175
176  pub fn is_value(&self) -> bool {
177    matches!(self, Component::Value(_))
178  }
179}
180
181impl fmt::Display for Component {
182  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183    write!(
184      f,
185      "{}",
186      match self {
187        Component::Any => "*".to_owned(),
188        Component::NA => "-".to_owned(),
189        Component::Value(v) => v.to_owned(),
190      }
191    )
192  }
193}