1use 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
11const CHECKSUM_PREFIX: &str = "checksum ";
13
14pub type Metadata = Map<MetadataKey, MetadataValue>;
16
17#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
19pub struct MetadataKey(String);
20
21impl MetadataKey {
22 pub fn for_checksum(dep: &Dependency) -> Self {
24 MetadataKey(format!("{CHECKSUM_PREFIX}{dep}"))
25 }
26
27 pub fn is_checksum(&self) -> bool {
29 self.0.starts_with(CHECKSUM_PREFIX)
30 }
31
32 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#[derive(Clone, Debug, Eq, PartialEq)]
91pub struct MetadataValue(String);
92
93impl MetadataValue {
94 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}