Skip to content

Commit 5a1db27

Browse files
committed
Using generated code for manifest serializing/deserializing instead of custom parsers
1 parent 2a14b6e commit 5a1db27

File tree

3 files changed

+78
-112
lines changed

3 files changed

+78
-112
lines changed

flake.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/manifest.rs

Lines changed: 65 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub const CANARY_EDITION: &str = concat!("0.", env!("CARGO_PKG_VERSION_MINOR"));
3838

3939
/// Edition of the buffrs manifest
4040
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
41-
#[serde(into = "&str", from = "&str")]
41+
#[serde(into = "Cow<str>", from = "Cow<str>")]
4242
pub enum Edition {
4343
/// The canary edition of manifests
4444
///
@@ -64,9 +64,22 @@ impl Edition {
6464
}
6565
}
6666

67-
impl From<&str> for Edition {
68-
fn from(value: &str) -> Self {
69-
match value {
67+
use std::borrow::Cow;
68+
69+
impl<'a> From<&'a str> for Edition {
70+
fn from(value: &'a str) -> Self {
71+
match &*value {
72+
self::CANARY_EDITION => Self::Canary,
73+
"0.8" => Self::Canary08,
74+
"0.7" => Self::Canary07,
75+
_ => Self::Unknown,
76+
}
77+
}
78+
}
79+
80+
impl<'a> From<Cow<'a, str>> for Edition {
81+
fn from(value: Cow<'a, str>) -> Self {
82+
match &*value {
7083
self::CANARY_EDITION => Self::Canary,
7184
"0.8" => Self::Canary08,
7285
"0.7" => Self::Canary07,
@@ -86,13 +99,26 @@ impl From<Edition> for &'static str {
8699
}
87100
}
88101

102+
impl From<Edition> for Cow<'static, str> {
103+
fn from(value: Edition) -> Self {
104+
Cow::Borrowed(match value {
105+
Edition::Canary => CANARY_EDITION,
106+
Edition::Canary08 => "0.8",
107+
Edition::Canary07 => "0.7",
108+
Edition::Unknown => "unknown",
109+
})
110+
}
111+
}
112+
89113
/// A buffrs manifest format used for serialization and deserialization.
90114
///
91115
/// This contains the exact structure of the `Proto.toml` and skips
92116
/// empty fields.
93-
#[derive(Debug, Clone, PartialEq, Eq)]
117+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
118+
#[serde(untagged)]
94119
enum RawManifest {
95120
Canary {
121+
edition: Edition,
96122
package: Option<PackageManifest>,
97123
dependencies: DependencyMap,
98124
},
@@ -125,105 +151,44 @@ impl RawManifest {
125151
}
126152
}
127153

128-
mod serializer {
129-
use super::*;
130-
use serde::{ser::SerializeStruct, Serializer};
131-
132-
impl Serialize for RawManifest {
133-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
134-
where
135-
S: Serializer,
136-
{
137-
match *self {
138-
RawManifest::Canary {
139-
ref package,
140-
ref dependencies,
141-
} => {
142-
let mut s = serializer.serialize_struct("Canary", 3)?;
143-
s.serialize_field("edition", CANARY_EDITION)?;
144-
s.serialize_field("package", package)?;
145-
s.serialize_field("dependencies", dependencies)?;
146-
s.end()
147-
}
148-
RawManifest::Unknown {
149-
ref package,
150-
ref dependencies,
151-
} => {
152-
let mut s = serializer.serialize_struct("Unknown", 2)?;
153-
s.serialize_field("package", package)?;
154-
s.serialize_field("dependencies", dependencies)?;
155-
s.end()
156-
}
157-
}
154+
#[test]
155+
fn manifest() {
156+
let mut dependencies = HashMap::new();
157+
dependencies.insert(
158+
PackageName::new("foo".to_string()).unwrap(),
159+
LocalDependencyManifest {
160+
path: Path::new("/foo/bar").to_path_buf(),
158161
}
159-
}
160-
}
161-
162-
mod deserializer {
163-
use serde::{
164-
de::{self, MapAccess, Visitor},
165-
Deserializer,
162+
.into(),
163+
);
164+
let man = RawManifest::Canary {
165+
edition: Edition::from(CANARY_EDITION),
166+
package: None,
167+
dependencies,
166168
};
169+
let x = toml::to_string(&man).unwrap();
170+
assert_eq!(
171+
x,
172+
format!(
173+
"edition = \"{}\"\n\n[dependencies.foo]\npath = \"/foo/bar\"\n",
174+
CANARY_EDITION
175+
)
176+
);
167177

168-
use super::*;
169-
170-
impl<'de> Deserialize<'de> for RawManifest {
171-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
172-
where
173-
D: Deserializer<'de>,
174-
{
175-
static FIELDS: &[&str] = &["package", "dependencies"];
176-
177-
struct ManifestVisitor;
178-
179-
impl<'de> Visitor<'de> for ManifestVisitor {
180-
type Value = RawManifest;
181-
182-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
183-
formatter.write_str("a buffrs manifest (`Proto.toml`)")
184-
}
185-
186-
fn visit_map<V>(self, mut map: V) -> Result<RawManifest, V::Error>
187-
where
188-
V: MapAccess<'de>,
189-
{
190-
let mut edition: Option<String> = None;
191-
let mut package: Option<PackageManifest> = None;
192-
let mut dependencies: Option<HashMap<PackageName, DependencyManifest>> = None;
193-
194-
while let Some(key) = map.next_key::<String>()? {
195-
match key.as_str() {
196-
"package" => package = Some(map.next_value()?),
197-
"dependencies" => dependencies = Some(map.next_value()?),
198-
"edition" => edition = Some(map.next_value()?),
199-
_ => return Err(de::Error::unknown_field(&key, FIELDS)),
200-
}
201-
}
202-
203-
let dependencies = dependencies.unwrap_or_default();
204-
205-
let Some(edition) = edition else {
206-
return Ok(RawManifest::Unknown {
207-
package,
208-
dependencies,
209-
});
210-
};
211-
212-
match Edition::from(edition.as_str()) {
213-
Edition::Canary | Edition::Canary08 | Edition::Canary07 => Ok(RawManifest::Canary {
214-
package,
215-
dependencies,
216-
}),
217-
Edition::Unknown => Err(de::Error::custom(
218-
format!("unsupported manifest edition, supported editions of {} are: {CANARY_EDITION}", env!("CARGO_PKG_VERSION"))
219-
)),
220-
}
221-
}
222-
}
178+
assert_eq!(toml::from_str::<RawManifest>(&x).unwrap(), man);
179+
}
223180

224-
deserializer.deserialize_map(ManifestVisitor)
225-
}
181+
#[test]
182+
fn canary() {
183+
let ed = Edition::from(CANARY_EDITION);
184+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
185+
struct Ed {
186+
ed: Edition,
226187
}
188+
let ed = Ed { ed };
189+
let x = toml::to_string(&ed).unwrap();
190+
assert_eq!(x, format!("ed = \"{}\"\n", CANARY_EDITION));
191+
assert_eq!(toml::from_str::<Ed>(&x).unwrap(), ed);
227192
}
228193

229194
impl From<Manifest> for RawManifest {
@@ -236,6 +201,7 @@ impl From<Manifest> for RawManifest {
236201

237202
match manifest.edition {
238203
Edition::Canary | Edition::Canary08 | Edition::Canary07 => RawManifest::Canary {
204+
edition: manifest.edition,
239205
package: manifest.package,
240206
dependencies,
241207
},

src/resolver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl DependencyGraph {
313313
path, dependants, ..
314314
} => {
315315
bail!(
316-
"a dependency of your project requires {}@{} which collides with a local dependency for {}@{} required by {:?}",
316+
"a dependency of your project requires {}@{} which collides with a local dependency for {}@{} required by {:?}",
317317
dependency.package,
318318
dependency.manifest.version,
319319
dependency.package,

0 commit comments

Comments
 (0)