1use std::ops::Deref;
2
3use relative_path::RelativePathBuf;
4use time::OffsetDateTime;
5
6use crate::{Line, Origin, Properties, Revision, test_runs::TestCaseState};
7
8use super::requirements::ReqId;
9
10pub const REVIEW_DATE_FORMAT: &[time::format_description::BorrowedFormatItem<'static>] = time::macros::format_description!(
16 "[year]-[month]-[day][first [T] [ ]][hour]:[minute][optional [:[second][optional [.[subsecond]]]]]utc[offset_hour sign:mandatory]"
17);
18
19time::serde::format_description!(pub review_date_format, OffsetDateTime, REVIEW_DATE_FORMAT);
20
21pub fn date_from_str(date: &str) -> Result<OffsetDateTime, time::error::Parse> {
23 OffsetDateTime::parse(date, REVIEW_DATE_FORMAT)
24 .or_else(|_| super::test_runs::test_date_from_str(date))
25}
26
27#[derive(
30 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
31)]
32#[serde(rename_all = "snake_case", deny_unknown_fields)]
33pub struct ReviewSchema {
34 #[serde(serialize_with = "crate::serialize_schema_version")]
37 pub schema_version: Option<String>,
38 pub reviews: Vec<Review>,
39 pub properties: Option<Properties>,
44 pub origin: Option<Origin>,
47}
48
49#[derive(
52 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
53)]
54#[serde(rename_all = "snake_case", deny_unknown_fields)]
55pub struct Review {
56 pub name: String,
59 #[serde(with = "review_date_format")]
62 #[schemars(
63 with = "String",
64 regex(
65 pattern = r"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(T| )(?<hour>\d{2}):(?<minute>\d{2})(?<second>:\d{2}(?<subsecond>\.\d{3})?)?utc(?<utc>(-|+)\d{2})"
66 )
67 )]
68 pub utc_date: OffsetDateTime,
69 pub authors: Vec<String>,
72 pub description: Option<String>,
75 pub origin: Option<Origin>,
78 pub properties: Option<Properties>,
80 pub revisions: Option<Vec<Revision>>,
82 #[serde(alias = "requirement", default)]
85 pub requirements: Vec<VerifiedRequirementGroup>,
86 #[serde(alias = "override", default)]
89 pub test_run_overrides: Vec<OverrideTestRun>,
90}
91
92#[derive(
95 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
96)]
97#[serde(deny_unknown_fields)]
98pub struct VerifiedRequirementGroup {
99 #[serde(alias = "ids")]
101 pub id: OneOrMultRequirementIds,
102 pub comment: String,
104}
105
106#[derive(
108 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
109)]
110#[serde(untagged)]
111pub enum OneOrMultRequirementIds {
112 One(ReqId),
114 Mult(Vec<ReqId>),
116}
117
118impl std::fmt::Display for OneOrMultRequirementIds {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 match &self {
121 OneOrMultRequirementIds::One(req_id) => write!(f, "{}", req_id),
122 OneOrMultRequirementIds::Mult(req_ids) => {
123 write!(
124 f,
125 "{}",
126 req_ids
127 .iter()
128 .map(|r| r.deref().clone())
129 .collect::<Vec<String>>()
130 .join(",")
131 )
132 }
133 }
134 }
135}
136
137#[derive(
140 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
141)]
142#[serde(rename_all = "snake_case", deny_unknown_fields)]
143pub struct OverrideTestRun {
144 pub name: String,
146 #[serde(with = "time::serde::iso8601")]
148 #[schemars(with = "String")]
149 pub utc_date: time::OffsetDateTime,
150 #[serde(alias = "test", default)]
153 pub test_cases: Vec<OverrideTestCase>,
154 #[serde(default)]
157 pub coverage: Vec<OverrideFileCoverage>,
158}
159
160#[derive(
163 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
164)]
165#[serde(deny_unknown_fields)]
166pub struct OverrideTestCase {
167 pub name: String,
169 pub state: Option<OverrideTestCaseState>,
172 #[serde(default)]
175 pub coverage: Vec<OverrideFileCoverage>,
176}
177
178#[derive(
181 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
182)]
183#[serde(deny_unknown_fields)]
184pub struct OverrideTestCaseState {
185 pub new: TestCaseState,
187 pub comment: String,
189}
190
191#[derive(
194 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
195)]
196#[serde(deny_unknown_fields)]
197pub struct OverrideFileCoverage {
198 #[schemars(with = "String")]
200 pub filepath: RelativePathBuf,
201 #[serde(default)]
203 pub lines: Vec<OverrideCoveredLineInfo>,
204}
205
206#[derive(
209 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
210)]
211#[serde(deny_unknown_fields)]
212pub struct OverrideCoveredLineInfo {
213 #[serde(alias = "nr")]
215 pub nrs: Vec<Line>,
216 pub hits: Option<i64>,
219 pub comment: String,
221}