1use crate::error::{CPEError, Result};
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::{fmt, str::FromStr};
5
6#[derive(Debug, Clone, PartialEq, Eq, Default)]
7pub enum Part {
8 #[default]
10 Any,
11 Hardware,
13 OperatingSystem,
15 Application,
17}
18
19impl Serialize for Part {
20 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
21 where
22 S: Serializer,
23 {
24 serializer.serialize_str(match *self {
25 Part::Any => "*",
26 Part::Hardware => "h",
27 Part::Application => "a",
28 Part::OperatingSystem => "o",
29 })
30 }
31}
32
33impl<'de> Deserialize<'de> for Part {
34 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
35 where
36 D: Deserializer<'de>,
37 {
38 let s = String::deserialize(deserializer)?;
39 Ok(match s.as_str() {
40 "h" => Part::Hardware,
41 "o" => Part::OperatingSystem,
42 "a" => Part::Application,
43 _ => Part::Any,
44 })
45 }
46}
47
48impl From<Part> for char {
49 fn from(val: Part) -> Self {
50 match val {
51 Part::Any => '*',
52 Part::Hardware => 'h',
53 Part::OperatingSystem => 'o',
54 Part::Application => 'a',
55 }
56 }
57}
58impl FromStr for Part {
59 type Err = CPEError;
60
61 fn from_str(val: &str) -> Result<Self> {
62 let c = {
63 let c = val.chars().next();
64 c.ok_or(CPEError::InvalidPart {
65 value: val.to_string(),
66 })?
67 };
68 match c {
69 'h' => Ok(Self::Hardware),
70 'o' => Ok(Self::OperatingSystem),
71 'a' => Ok(Self::Application),
72 _ => Err(CPEError::InvalidPart {
73 value: c.to_string(),
74 }),
75 }
76 }
77}
78
79impl fmt::Display for Part {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 match self {
82 Self::Hardware => write!(f, "h"),
83 Self::OperatingSystem => write!(f, "o"),
84 Self::Application => write!(f, "a"),
85 Self::Any => {
86 if f.alternate() {
87 write!(f, "*")
88 } else {
89 write!(f, "ANY")
90 }
91 }
92 }
93 }
94}