1use crate::dependencies::{Dependency, Patch, RegistryPatch, TargetDependencies};
2use serde::ser::{SerializeMap, Serializer};
3use serde_derive::{Deserialize, Serialize};
4use std::collections::BTreeMap as Map;
5use std::ffi::OsStr;
6use std::path::PathBuf;
7
8#[derive(Serialize, Debug)]
9pub struct Manifest {
10 pub package: Package,
11 #[serde(skip_serializing_if = "Map::is_empty")]
12 pub features: Map<String, Vec<String>>,
13 pub dependencies: Map<String, Dependency>,
14 #[serde(skip_serializing_if = "Map::is_empty")]
15 pub target: Map<String, TargetDependencies>,
16 #[serde(rename = "bin")]
17 pub bins: Vec<Bin>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub workspace: Option<Workspace>,
20 #[serde(
21 serialize_with = "serialize_patch",
22 skip_serializing_if = "empty_patch"
23 )]
24 pub patch: Map<String, RegistryPatch>,
25 #[serde(skip_serializing_if = "Map::is_empty")]
26 pub replace: Map<String, Patch>,
27}
28
29#[derive(Serialize, Debug)]
30pub struct Package {
31 pub name: String,
32 pub version: String,
33 pub edition: Edition,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub resolver: Option<String>,
36 pub publish: bool,
37}
38
39#[derive(Serialize, Deserialize, Debug)]
40pub enum Edition {
41 #[serde(rename = "2015")]
42 E2015,
43 #[serde(rename = "2018")]
44 E2018,
45 #[serde(rename = "2021")]
46 E2021,
47}
48
49#[derive(Serialize, Debug)]
50pub struct Bin {
51 pub name: Name,
52 pub path: PathBuf,
53}
54
55#[derive(Serialize, Clone, Debug)]
56pub struct Name(pub String);
57
58#[derive(Serialize, Debug)]
59pub struct Config {
60 pub build: Build,
61}
62
63#[derive(Serialize, Debug)]
64pub struct Build {
65 pub rustflags: Vec<&'static str>,
66}
67
68#[derive(Serialize, Debug)]
69pub struct Workspace {
70 #[serde(skip_serializing_if = "Map::is_empty")]
71 pub dependencies: Map<String, Dependency>,
72}
73
74impl Default for Edition {
75 fn default() -> Self {
76 Edition::E2018
77 }
78}
79
80impl AsRef<OsStr> for Name {
81 fn as_ref(&self) -> &OsStr {
82 self.0.as_ref()
83 }
84}
85
86fn serialize_patch<S>(patch: &Map<String, RegistryPatch>, serializer: S) -> Result<S::Ok, S::Error>
87where
88 S: Serializer,
89{
90 let mut map = serializer.serialize_map(None)?;
91 for (registry, patch) in patch {
92 if !patch.crates.is_empty() {
93 map.serialize_entry(registry, patch)?;
94 }
95 }
96 map.end()
97}
98
99fn empty_patch(patch: &Map<String, RegistryPatch>) -> bool {
100 patch
101 .values()
102 .all(|registry_patch| registry_patch.crates.is_empty())
103}
104