qubit_validator/report/skipped_validation.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Explicitly skipped validation occurrences.
10
11use super::FailureId;
12use super::SkipReason;
13use super::ValidationOutcomeError;
14use super::ValidationPath;
15
16/// One validation occurrence that was skipped by the executor.
17///
18/// # Examples
19///
20/// ```
21/// use qubit_validator::{SkipReason, SkippedValidation, ValidationPath};
22///
23/// let skipped = SkippedValidation::missing_optional(
24/// 0,
25/// ValidationPath::root().with_field("optional"),
26/// );
27/// assert_eq!(skipped.reason(), SkipReason::MissingOptional);
28/// ```
29#[must_use]
30#[derive(Clone, Debug, Eq, PartialEq)]
31pub struct SkippedValidation {
32 /// Zero-based declaration occurrence assigned by the executor.
33 occurrence: usize,
34 /// Structured path of the skipped target.
35 path: ValidationPath,
36 /// Policy reason the occurrence did not execute.
37 reason: SkipReason,
38 /// IDs of failures that prevented this occurrence; empty for an absent
39 /// optional target.
40 prerequisites: Vec<FailureId>,
41}
42
43impl SkippedValidation {
44 /// Creates a record for an absent optional target.
45 ///
46 /// # Parameters
47 ///
48 /// - `occurrence`: Zero-based declaration position of the skipped target.
49 /// - `path`: Structured path identifying the absent target.
50 ///
51 /// # Returns
52 ///
53 /// A skipped occurrence with no prerequisite failures.
54 #[inline]
55 pub fn missing_optional(occurrence: usize, path: ValidationPath) -> Self {
56 Self {
57 occurrence,
58 path,
59 reason: SkipReason::MissingOptional,
60 prerequisites: Vec::new(),
61 }
62 }
63
64 /// Creates a record for an occurrence skipped after prerequisite
65 /// failures.
66 ///
67 /// # Parameters
68 ///
69 /// - `occurrence`: Zero-based declaration position of the skipped target.
70 /// - `path`: Structured path identifying the skipped target.
71 /// - `prerequisites`: Failure IDs that prevented this occurrence from
72 /// running.
73 ///
74 /// # Errors
75 ///
76 /// Returns `EmptyPrerequisites` when no failure ID is supplied.
77 ///
78 /// # Returns
79 ///
80 /// A skipped occurrence containing the supplied prerequisite failure IDs.
81 pub fn failed_prerequisite(
82 occurrence: usize,
83 path: ValidationPath,
84 prerequisites: Vec<FailureId>,
85 ) -> Result<Self, ValidationOutcomeError> {
86 if prerequisites.is_empty() {
87 return Err(ValidationOutcomeError::EmptyPrerequisites);
88 }
89 Ok(Self {
90 occurrence,
91 path,
92 reason: SkipReason::FailedPrerequisite,
93 prerequisites,
94 })
95 }
96
97 /// Returns the zero-based declaration occurrence assigned by the executor.
98 ///
99 /// # Returns
100 ///
101 /// The occurrence number used to order this validation result.
102 #[must_use]
103 #[inline]
104 pub const fn occurrence(&self) -> usize {
105 self.occurrence
106 }
107
108 /// Returns the structured path of the skipped target.
109 ///
110 /// # Returns
111 ///
112 /// A borrow of the target path stored in this record.
113 #[must_use]
114 #[inline]
115 pub const fn path(&self) -> &ValidationPath {
116 &self.path
117 }
118
119 /// Returns why the executor did not run this occurrence.
120 ///
121 /// # Returns
122 ///
123 /// The policy reason that caused the skip.
124 #[must_use]
125 #[inline]
126 pub const fn reason(&self) -> SkipReason {
127 self.reason
128 }
129
130 /// Returns IDs of failures that prevented this occurrence.
131 ///
132 /// # Returns
133 ///
134 /// The prerequisite IDs, or an empty slice when an optional target was
135 /// absent.
136 #[must_use = "inspect the prerequisite failure IDs"]
137 #[inline]
138 pub fn prerequisites(&self) -> &[FailureId] {
139 &self.prerequisites
140 }
141}