qubit-validator 0.1.0

Type-safe validation traits and registries for Qubit applications
Documentation
// =============================================================================
//    Copyright (c) 2025 - 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================

//! Explicitly skipped validation occurrences.

use super::FailureId;
use super::SkipReason;
use super::ValidationOutcomeError;
use super::ValidationPath;

/// One validation occurrence that was skipped by the executor.
///
/// # Examples
///
/// ```
/// use qubit_validator::{SkipReason, SkippedValidation, ValidationPath};
///
/// let skipped = SkippedValidation::missing_optional(
///     0,
///     ValidationPath::root().with_field("optional"),
/// );
/// assert_eq!(skipped.reason(), SkipReason::MissingOptional);
/// ```
#[must_use]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SkippedValidation {
    /// Zero-based declaration occurrence assigned by the executor.
    occurrence: usize,
    /// Structured path of the skipped target.
    path: ValidationPath,
    /// Policy reason the occurrence did not execute.
    reason: SkipReason,
    /// IDs of failures that prevented this occurrence; empty for an absent
    /// optional target.
    prerequisites: Vec<FailureId>,
}

impl SkippedValidation {
    /// Creates a record for an absent optional target.
    ///
    /// # Parameters
    ///
    /// - `occurrence`: Zero-based declaration position of the skipped target.
    /// - `path`: Structured path identifying the absent target.
    ///
    /// # Returns
    ///
    /// A skipped occurrence with no prerequisite failures.
    #[inline]
    pub fn missing_optional(occurrence: usize, path: ValidationPath) -> Self {
        Self {
            occurrence,
            path,
            reason: SkipReason::MissingOptional,
            prerequisites: Vec::new(),
        }
    }

    /// Creates a record for an occurrence skipped after prerequisite
    /// failures.
    ///
    /// # Parameters
    ///
    /// - `occurrence`: Zero-based declaration position of the skipped target.
    /// - `path`: Structured path identifying the skipped target.
    /// - `prerequisites`: Failure IDs that prevented this occurrence from
    ///   running.
    ///
    /// # Errors
    ///
    /// Returns `EmptyPrerequisites` when no failure ID is supplied.
    ///
    /// # Returns
    ///
    /// A skipped occurrence containing the supplied prerequisite failure IDs.
    pub fn failed_prerequisite(
        occurrence: usize,
        path: ValidationPath,
        prerequisites: Vec<FailureId>,
    ) -> Result<Self, ValidationOutcomeError> {
        if prerequisites.is_empty() {
            return Err(ValidationOutcomeError::EmptyPrerequisites);
        }
        Ok(Self {
            occurrence,
            path,
            reason: SkipReason::FailedPrerequisite,
            prerequisites,
        })
    }

    /// Returns the zero-based declaration occurrence assigned by the executor.
    ///
    /// # Returns
    ///
    /// The occurrence number used to order this validation result.
    #[must_use]
    #[inline]
    pub const fn occurrence(&self) -> usize {
        self.occurrence
    }

    /// Returns the structured path of the skipped target.
    ///
    /// # Returns
    ///
    /// A borrow of the target path stored in this record.
    #[must_use]
    #[inline]
    pub const fn path(&self) -> &ValidationPath {
        &self.path
    }

    /// Returns why the executor did not run this occurrence.
    ///
    /// # Returns
    ///
    /// The policy reason that caused the skip.
    #[must_use]
    #[inline]
    pub const fn reason(&self) -> SkipReason {
        self.reason
    }

    /// Returns IDs of failures that prevented this occurrence.
    ///
    /// # Returns
    ///
    /// The prerequisite IDs, or an empty slice when an optional target was
    /// absent.
    #[must_use = "inspect the prerequisite failure IDs"]
    #[inline]
    pub fn prerequisites(&self) -> &[FailureId] {
        &self.prerequisites
    }
}