rustsec/
collection.rs

1//! Package collections
2
3use crate::error::{Error, ErrorKind};
4use serde::{de, ser, Deserialize, Serialize};
5use std::{fmt, str::FromStr};
6
7/// Collections of packages (`crates` vs `rust`).
8///
9/// Advisories are either filed against crates published to <https://crates.io>
10/// or packages provided by the Rust language itself (e.g. `std`, `rustdoc`)
11#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
12pub enum Collection {
13    /// Crates published through crates.io
14    Crates,
15
16    /// Rust core vulnerabilities
17    Rust,
18}
19
20impl Collection {
21    /// Get all collections as a slice
22    pub fn all() -> &'static [Self] {
23        &[Collection::Crates, Collection::Rust]
24    }
25
26    /// Get a `str` representing the kind of package
27    pub fn as_str(&self) -> &str {
28        match self {
29            Collection::Crates => "crates",
30            Collection::Rust => "rust",
31        }
32    }
33}
34
35impl fmt::Display for Collection {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(f, "{}", self.as_str())
38    }
39}
40
41impl FromStr for Collection {
42    type Err = Error;
43
44    fn from_str(s: &str) -> Result<Self, Error> {
45        Ok(match s {
46            "crates" => Collection::Crates,
47            "rust" => Collection::Rust,
48            other => fail!(ErrorKind::Parse, "invalid package type: {}", other),
49        })
50    }
51}
52
53impl<'de> Deserialize<'de> for Collection {
54    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
55        use de::Error;
56        let string = String::deserialize(deserializer)?;
57        string.parse().map_err(D::Error::custom)
58    }
59}
60
61impl Serialize for Collection {
62    fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
63        self.to_string().serialize(serializer)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::Collection;
70
71    #[test]
72    fn parse_crate() {
73        let crate_kind = "crates".parse::<Collection>().unwrap();
74        assert_eq!(Collection::Crates, crate_kind);
75        assert_eq!("crates", crate_kind.as_str());
76    }
77
78    #[test]
79    fn parse_rust() {
80        let rust_kind = "rust".parse::<Collection>().unwrap();
81        assert_eq!(Collection::Rust, rust_kind);
82        assert_eq!("rust", rust_kind.as_str());
83    }
84
85    #[test]
86    fn parse_other() {
87        assert!("foobar".parse::<Collection>().is_err());
88    }
89}