backhopper_core/model/
check_payload.rs1use std::collections::{BTreeMap, BTreeSet};
10
11use serde::{Deserialize, Serialize};
12
13use crate::model::apply::ApplyForecast;
14use crate::model::batch::PinPayload;
15use crate::model::evaluation::{
16 AggregateVerdict, BehaviourModuleMissingFinding, HeaderFileMissingFinding,
17 SeriesEvaluationView, TestModuleSymbolMissingFinding, VersionedMachineSnapshotMissingFinding,
18 WireConstantBindingsMissingFinding,
19};
20use crate::model::findings::TargetFindings;
21use crate::model::fingerprint::VerdictFingerprint;
22use crate::model::names::{ModuleName, ProjectName, RelativePath, SeriesName, TagName};
23use crate::model::pin::Pin;
24use crate::model::pr_commit::PrCommit;
25use crate::model::producer::Producer;
26use crate::model::resolver_coverage::ResolverCoverage;
27use crate::model::summary::VerdictKind;
28use crate::model::verdict::{Diagnostics, PinVerdict, Reason, SeriesVerdict};
29
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
34pub struct ProjectSuggestion {
35 pub name: String,
36 pub modules: Vec<String>,
37 pub call_sites: usize,
38}
39
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
43#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
44#[serde(tag = "kind", rename_all = "snake_case")]
45pub enum QueriedAgainst {
46 Pin { project: ProjectName, tag: TagName },
48 Series {
50 name: SeriesName,
51 pins: Vec<PinPayload>,
52 },
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
58pub struct CheckPayload {
59 pub queried_against: QueriedAgainst,
61 pub results: SeriesVerdict,
63 #[serde(default, skip_serializing_if = "Diagnostics::is_empty")]
65 pub diagnostics: Diagnostics,
66 #[serde(default, skip_serializing_if = "Vec::is_empty")]
68 pub project_suggestions: Vec<ProjectSuggestion>,
69 #[serde(default)]
73 pub pr_commits: Option<Vec<PrCommit>>,
74 #[serde(default)]
77 pub self_projects: Option<BTreeSet<ProjectName>>,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub verdict_fingerprint: Option<VerdictFingerprint>,
82 #[serde(default)]
85 pub resolver_coverage: Option<ResolverCoverage>,
86 #[serde(default)]
88 pub fingerprint_version: Option<u32>,
89 #[serde(default, skip_serializing_if = "Option::is_none")]
92 pub apply: Option<ApplyForecast>,
93 #[serde(default, skip_serializing_if = "Option::is_none")]
95 pub target_findings: Option<TargetFindings>,
96}
97
98impl CheckPayload {
99 #[must_use]
103 pub fn view(&self) -> SeriesEvaluationView<'_> {
104 SeriesEvaluationView::new(&self.results, &self.diagnostics)
105 }
106
107 #[must_use]
110 pub fn producer(&self) -> Producer<'_> {
111 Producer::from_fields(
112 self.self_projects.as_ref(),
113 self.resolver_coverage.as_ref(),
114 self.fingerprint_version,
115 )
116 }
117
118 #[must_use]
121 pub fn tracked_refs(&self) -> Option<u32> {
122 match self.producer() {
123 Producer::Current { self_projects, .. } => {
124 Some(self.view().tracked_refs(self_projects))
125 }
126 Producer::BeforeV12 => None,
127 }
128 }
129
130 #[must_use]
132 pub fn worst_verdict(&self) -> AggregateVerdict {
133 self.view().worst_verdict()
134 }
135
136 #[must_use]
138 pub fn has_blocking_reason(&self) -> bool {
139 self.view().has_blocking_reason()
140 }
141
142 pub fn pins_in(&self, verdict: VerdictKind) -> impl Iterator<Item = &PinVerdict> {
144 self.view().pins_in(verdict)
145 }
146
147 pub fn reasons_for(&self, pin: &Pin) -> impl Iterator<Item = &Reason> {
149 self.view().reasons_for(pin)
150 }
151
152 #[must_use]
154 pub fn pin_by_project(&self, project: &ProjectName) -> Option<&PinVerdict> {
155 self.view().pin_by_project(project)
156 }
157
158 #[must_use]
160 pub fn missing_test_modules(&self) -> &BTreeMap<RelativePath, BTreeMap<ModuleName, usize>> {
161 self.view().missing_test_modules()
162 }
163
164 pub fn test_module_symbol_missing(
166 &self,
167 ) -> impl Iterator<Item = TestModuleSymbolMissingFinding<'_>> {
168 self.view().test_module_symbol_missing()
169 }
170
171 pub fn header_file_missing(&self) -> impl Iterator<Item = HeaderFileMissingFinding<'_>> {
173 self.view().header_file_missing()
174 }
175
176 pub fn behaviour_module_missing(
178 &self,
179 ) -> impl Iterator<Item = BehaviourModuleMissingFinding<'_>> {
180 self.view().behaviour_module_missing()
181 }
182
183 pub fn versioned_machine_snapshot_missing(
185 &self,
186 ) -> impl Iterator<Item = VersionedMachineSnapshotMissingFinding<'_>> {
187 self.view().versioned_machine_snapshot_missing()
188 }
189
190 pub fn wire_constant_bindings_missing(
192 &self,
193 ) -> impl Iterator<Item = WireConstantBindingsMissingFinding<'_>> {
194 self.view().wire_constant_bindings_missing()
195 }
196}