db_dump/
dependencies.rs

1//! <b style="font-variant:small-caps">dependencies.csv</b>
2
3use crate::crates::CrateId;
4use crate::versions::VersionId;
5use semver::VersionReq;
6use serde::de::{Deserialize, Deserializer, Unexpected, Visitor};
7use serde_derive::Deserialize;
8use std::fmt;
9
10/// One row of **dependencies.csv**.
11#[derive(Deserialize, Clone, Debug)]
12#[serde(deny_unknown_fields)]
13#[non_exhaustive]
14pub struct Row {
15    /// PRIMARY KEY
16    pub id: u32,
17    pub version_id: VersionId,
18    pub crate_id: CrateId,
19    #[serde(deserialize_with = "version_req")]
20    pub req: VersionReq,
21    #[serde(deserialize_with = "crate::bool::de")]
22    pub optional: bool,
23    #[serde(deserialize_with = "crate::bool::de")]
24    pub default_features: bool,
25    #[serde(deserialize_with = "features_set")]
26    pub features: Vec<String>,
27    pub target: String,
28    pub kind: DependencyKind,
29    #[serde(default)]
30    pub explicit_name: Option<String>,
31}
32
33#[derive(Copy, Clone, Debug)]
34pub enum DependencyKind {
35    /// kind=0
36    Normal,
37    /// kind=1
38    Build,
39    /// kind=2
40    Dev,
41}
42
43struct DependencyKindVisitor;
44
45impl<'de> Visitor<'de> for DependencyKindVisitor {
46    type Value = DependencyKind;
47
48    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
49        formatter.write_str("dependency kind (0, 1, 2)")
50    }
51
52    fn visit_u8<E>(self, kind: u8) -> Result<Self::Value, E>
53    where
54        E: serde::de::Error,
55    {
56        match kind {
57            0 => Ok(DependencyKind::Normal),
58            1 => Ok(DependencyKind::Build),
59            2 => Ok(DependencyKind::Dev),
60            _ => Err(serde::de::Error::invalid_value(
61                Unexpected::Unsigned(kind as u64),
62                &self,
63            )),
64        }
65    }
66}
67
68impl<'de> Deserialize<'de> for DependencyKind {
69    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        deserializer.deserialize_u8(DependencyKindVisitor)
74    }
75}
76
77fn compat(string: &str) -> Option<VersionReq> {
78    let deprecated = match string {
79        "^0-.11.0" => "^0.11.0",
80        "^0.1-alpha.0" => "^0.1.0-alpha.0",
81        "^0.51-oldsyn" => "^0.51.1-oldsyn",
82        "~2.0-2.2" => ">=2.0, <=2.2",
83        _ => return None,
84    };
85    Some(deprecated.parse().unwrap())
86}
87
88struct VersionReqVisitor;
89
90impl<'de> Visitor<'de> for VersionReqVisitor {
91    type Value = VersionReq;
92
93    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
94        formatter.write_str("semver version req")
95    }
96
97    fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
98    where
99        E: serde::de::Error,
100    {
101        match string.parse() {
102            Ok(version) => Ok(version),
103            Err(err) => {
104                if let Some(version) = compat(string) {
105                    Ok(version)
106                } else {
107                    Err(serde::de::Error::custom(format_args!(
108                        "{}: req {}",
109                        err, string,
110                    )))
111                }
112            }
113        }
114    }
115}
116
117fn version_req<'de, D>(deserializer: D) -> Result<VersionReq, D::Error>
118where
119    D: Deserializer<'de>,
120{
121    deserializer.deserialize_str(VersionReqVisitor)
122}
123
124fn features_set<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
125where
126    D: Deserializer<'de>,
127{
128    crate::set::de(deserializer, "features set")
129}