cargo_lock/
metadata.rs

1//! Package metadata
2
3use crate::{
4    error::{Error, Result},
5    lockfile::encoding::EncodableDependency,
6    Checksum, Dependency, Map,
7};
8use serde::{de, ser, Deserialize, Serialize};
9use std::{fmt, str::FromStr};
10
11/// Prefix of metadata keys for checksum entries
12const CHECKSUM_PREFIX: &str = "checksum ";
13
14/// Package metadata
15pub type Metadata = Map<MetadataKey, MetadataValue>;
16
17/// Keys for the `[metadata]` table
18#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
19pub struct MetadataKey(String);
20
21impl MetadataKey {
22    /// Create a metadata key for a checksum for the given dependency
23    pub fn for_checksum(dep: &Dependency) -> Self {
24        MetadataKey(format!("{CHECKSUM_PREFIX}{dep}"))
25    }
26
27    /// Is this metadata key a checksum entry?
28    pub fn is_checksum(&self) -> bool {
29        self.0.starts_with(CHECKSUM_PREFIX)
30    }
31
32    /// Get the dependency for a particular checksum value (if applicable)
33    pub fn checksum_dependency(&self) -> Result<Dependency> {
34        self.try_into()
35    }
36}
37
38impl AsRef<str> for MetadataKey {
39    fn as_ref(&self) -> &str {
40        &self.0
41    }
42}
43
44impl fmt::Display for MetadataKey {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{}", self.0)
47    }
48}
49
50impl FromStr for MetadataKey {
51    type Err = Error;
52
53    fn from_str(s: &str) -> Result<Self> {
54        Ok(MetadataKey(s.to_owned()))
55    }
56}
57
58impl TryFrom<&MetadataKey> for Dependency {
59    type Error = Error;
60
61    fn try_from(key: &MetadataKey) -> Result<Dependency> {
62        if !key.is_checksum() {
63            return Err(Error::Parse(
64                "can only parse dependencies from `checksum` metadata".to_owned(),
65            ));
66        }
67
68        let dep = EncodableDependency::from_str(&key.as_ref()[CHECKSUM_PREFIX.len()..])?;
69        (&dep).try_into()
70    }
71}
72
73impl<'de> Deserialize<'de> for MetadataKey {
74    fn deserialize<D: de::Deserializer<'de>>(
75        deserializer: D,
76    ) -> std::result::Result<Self, D::Error> {
77        String::deserialize(deserializer)?
78            .parse()
79            .map_err(de::Error::custom)
80    }
81}
82
83impl Serialize for MetadataKey {
84    fn serialize<S: ser::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
85        self.to_string().serialize(serializer)
86    }
87}
88
89/// Values in the `[metadata]` table
90#[derive(Clone, Debug, Eq, PartialEq)]
91pub struct MetadataValue(String);
92
93impl MetadataValue {
94    /// Get the associated checksum for this value (if applicable)
95    pub fn checksum(&self) -> Result<Checksum> {
96        self.try_into()
97    }
98}
99
100impl AsRef<str> for MetadataValue {
101    fn as_ref(&self) -> &str {
102        &self.0
103    }
104}
105
106impl fmt::Display for MetadataValue {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        write!(f, "{}", self.0)
109    }
110}
111
112impl FromStr for MetadataValue {
113    type Err = Error;
114
115    fn from_str(s: &str) -> Result<Self> {
116        Ok(MetadataValue(s.to_owned()))
117    }
118}
119
120impl TryFrom<&MetadataValue> for Checksum {
121    type Error = Error;
122
123    fn try_from(value: &MetadataValue) -> Result<Checksum> {
124        value.as_ref().parse()
125    }
126}
127
128impl<'de> Deserialize<'de> for MetadataValue {
129    fn deserialize<D: de::Deserializer<'de>>(
130        deserializer: D,
131    ) -> std::result::Result<Self, D::Error> {
132        String::deserialize(deserializer)?
133            .parse()
134            .map_err(de::Error::custom)
135    }
136}
137
138impl Serialize for MetadataValue {
139    fn serialize<S: ser::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
140        self.to_string().serialize(serializer)
141    }
142}