Skip to main content

qubit_fs/directory/
delete_options.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Delete operation options.
9
10use crate::error::FsError;
11use crate::error::FsErrorKind;
12use crate::error::FsOperation;
13use crate::metadata::FileSystemCapabilities;
14use crate::metadata::FileSystemCapability;
15use crate::metadata::ResourceVersion;
16
17/// Options controlling delete operations.
18///
19/// # Examples
20///
21/// ```rust
22/// use qubit_fs::directory::DeleteOptions;
23///
24/// assert!(!DeleteOptions::default().recursive());
25/// ```
26#[non_exhaustive]
27#[derive(Clone, Debug, Default, Eq, PartialEq)]
28pub struct DeleteOptions {
29    /// Whether container resources should be removed recursively.
30    recursive: bool,
31    /// Whether a missing target should be treated as success.
32    missing_ok: bool,
33    /// Optional required ETag or provider version.
34    if_match: Option<ResourceVersion>,
35}
36
37impl DeleteOptions {
38    /// Returns whether container resources should be removed recursively.
39    #[inline]
40    #[must_use]
41    pub const fn recursive(&self) -> bool {
42        self.recursive
43    }
44
45    /// Returns whether a missing target should be treated as success.
46    #[inline]
47    #[must_use]
48    pub const fn missing_ok(&self) -> bool {
49        self.missing_ok
50    }
51
52    /// Returns the optional required ETag or provider version.
53    #[inline]
54    #[must_use]
55    pub const fn if_match(&self) -> Option<&ResourceVersion> {
56        self.if_match.as_ref()
57    }
58
59    /// Replaces recursive container deletion.
60    #[inline]
61    #[must_use]
62    pub const fn with_recursive(mut self, recursive: bool) -> Self {
63        self.recursive = recursive;
64        self
65    }
66
67    /// Replaces missing-target acceptance.
68    #[inline]
69    #[must_use]
70    pub const fn with_missing_ok(mut self, missing_ok: bool) -> Self {
71        self.missing_ok = missing_ok;
72        self
73    }
74
75    /// Replaces the optional required ETag or provider version.
76    #[inline]
77    #[must_use]
78    pub fn with_if_match(mut self, if_match: Option<ResourceVersion>) -> Self {
79        self.if_match = if_match;
80        self
81    }
82
83    /// Validates required deletion semantics before provider side effects.
84    ///
85    /// # Errors
86    ///
87    /// Returns [`FsErrorKind::RequirementNotMet`] with the exact missing
88    /// recursive or conditional-delete capability.
89    pub fn validate_against(&self, capabilities: FileSystemCapabilities) -> Result<(), FsError> {
90        if self.recursive() && !capabilities.supports(FileSystemCapability::RecursiveDelete) {
91            return Err(missing_requirement(
92                FileSystemCapability::RecursiveDelete,
93                "recursive deletion is required but not supported",
94            ));
95        }
96        if self.if_match().is_some() && !capabilities.supports(FileSystemCapability::ConditionalDelete) {
97            return Err(missing_requirement(
98                FileSystemCapability::ConditionalDelete,
99                "conditional deletion is required but not supported",
100            ));
101        }
102        Ok(())
103    }
104}
105
106/// Builds a typed unmet delete requirement.
107fn missing_requirement(capability: FileSystemCapability, message: &str) -> FsError {
108    FsError::new(FsErrorKind::RequirementNotMet, FsOperation::Delete, message).with_required_capability(capability)
109}