trybuild_internals_api/
manifest.rs

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    #[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}