trybuild_internals_api/
manifest.rs1use 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 #[serde(rename = "cargo-features", skip_serializing_if = "Vec::is_empty")]
11 pub cargo_features: Vec<String>,
12 pub package: Package,
13 #[serde(skip_serializing_if = "Map::is_empty")]
14 pub features: Map<String, Vec<String>>,
15 pub dependencies: Map<String, Dependency>,
16 #[serde(skip_serializing_if = "Map::is_empty")]
17 pub target: Map<String, TargetDependencies>,
18 #[serde(rename = "bin")]
19 pub bins: Vec<Bin>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub workspace: Option<Workspace>,
22 #[serde(
23 serialize_with = "serialize_patch",
24 skip_serializing_if = "empty_patch"
25 )]
26 pub patch: Map<String, RegistryPatch>,
27 #[serde(skip_serializing_if = "Map::is_empty")]
28 pub replace: Map<String, Patch>,
29}
30
31#[derive(Serialize, Debug)]
32pub struct Package {
33 pub name: String,
34 pub version: String,
35 pub edition: Edition,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub resolver: Option<String>,
38 pub publish: bool,
39}
40
41#[derive(Serialize, Deserialize, Default, Debug)]
42pub enum Edition {
43 #[default]
44 #[serde(rename = "2015")]
45 E2015,
46 #[serde(rename = "2018")]
47 E2018,
48 #[serde(rename = "2021")]
49 E2021,
50 #[serde(rename = "2024")]
51 E2024,
52}
53
54#[derive(Serialize, Debug)]
55pub struct Bin {
56 pub name: Name,
57 pub path: PathBuf,
58}
59
60#[derive(Serialize, Clone, Debug)]
61pub struct Name(pub String);
62
63#[derive(Serialize, Debug)]
64pub struct Workspace {
65 #[serde(skip_serializing_if = "Map::is_empty")]
66 pub dependencies: Map<String, Dependency>,
67}
68
69impl AsRef<OsStr> for Name {
70 fn as_ref(&self) -> &OsStr {
71 self.0.as_ref()
72 }
73}
74
75fn serialize_patch<S>(patch: &Map<String, RegistryPatch>, serializer: S) -> Result<S::Ok, S::Error>
76where
77 S: Serializer,
78{
79 let mut map = serializer.serialize_map(None)?;
80 for (registry, patch) in patch {
81 if !patch.crates.is_empty() {
82 map.serialize_entry(registry, patch)?;
83 }
84 }
85 map.end()
86}
87
88fn empty_patch(patch: &Map<String, RegistryPatch>) -> bool {
89 patch
90 .values()
91 .all(|registry_patch| registry_patch.crates.is_empty())
92}