qubit_fs/metadata/
file_system_capabilities.rs1use std::fmt::Debug;
11use std::fmt::Formatter;
12use std::fmt::Result as FmtResult;
13
14use crate::metadata::FileSystemCapability;
15use crate::metadata::FileSystemCapabilitySupport;
16
17const CAPABILITY_DEPENDENCIES: &[(FileSystemCapability, FileSystemCapability)] = &[
18 (FileSystemCapability::RangeRead, FileSystemCapability::Read),
19 (FileSystemCapability::ConditionalRead, FileSystemCapability::Read),
20 (FileSystemCapability::ChecksumValidation, FileSystemCapability::Read),
21 (FileSystemCapability::Append, FileSystemCapability::Write),
22 (FileSystemCapability::ConditionalWrite, FileSystemCapability::Write),
23 (FileSystemCapability::AtomicReplace, FileSystemCapability::Write),
24 (FileSystemCapability::DurableWrite, FileSystemCapability::Write),
25 (FileSystemCapability::RecursiveDelete, FileSystemCapability::Delete),
26 (FileSystemCapability::ConditionalDelete, FileSystemCapability::Delete),
27 (FileSystemCapability::AtomicRename, FileSystemCapability::Rename),
28 (FileSystemCapability::ServerSideCopy, FileSystemCapability::Copy),
29 (FileSystemCapability::AtomicFileCopy, FileSystemCapability::Copy),
30 (FileSystemCapability::AtomicTreeCopy, FileSystemCapability::Copy),
31 (FileSystemCapability::DurableFileCopy, FileSystemCapability::Copy),
32 (FileSystemCapability::DurableTreeCopy, FileSystemCapability::Copy),
33 (FileSystemCapability::DurableRename, FileSystemCapability::Rename),
34];
35
36#[derive(Clone, Copy, Eq, PartialEq)]
65pub struct FileSystemCapabilities {
66 conditional: u128,
68 guaranteed: u128,
70}
71
72impl FileSystemCapabilities {
73 #[inline]
75 #[must_use]
76 pub const fn new() -> Self {
77 Self {
78 conditional: 0,
79 guaranteed: 0,
80 }
81 }
82
83 #[inline]
85 #[must_use]
86 pub const fn with_conditional(self, capability: FileSystemCapability) -> Self {
87 self.set_support(capability, FileSystemCapabilitySupport::Conditional)
88 }
89
90 #[inline]
92 #[must_use]
93 pub const fn with_guaranteed(self, capability: FileSystemCapability) -> Self {
94 self.set_support(capability, FileSystemCapabilitySupport::Guaranteed)
95 }
96
97 #[inline]
99 #[must_use]
100 pub const fn set_support(mut self, capability: FileSystemCapability, support: FileSystemCapabilitySupport) -> Self {
101 let bit = capability.bit();
102 self.conditional &= !bit;
103 self.guaranteed &= !bit;
104 match support {
105 FileSystemCapabilitySupport::Unsupported => {}
106 FileSystemCapabilitySupport::Conditional => {
107 self.conditional |= bit;
108 }
109 FileSystemCapabilitySupport::Guaranteed => {
110 self.guaranteed |= bit;
111 }
112 }
113 self
114 }
115
116 #[inline]
118 pub const fn support(&self, capability: FileSystemCapability) -> FileSystemCapabilitySupport {
119 let bit = capability.bit();
120 if self.guaranteed & bit != 0 {
121 FileSystemCapabilitySupport::Guaranteed
122 } else if self.conditional & bit != 0 {
123 FileSystemCapabilitySupport::Conditional
124 } else {
125 FileSystemCapabilitySupport::Unsupported
126 }
127 }
128
129 #[inline]
131 #[must_use]
132 pub const fn supports(&self, capability: FileSystemCapability) -> bool {
133 !matches!(self.support(capability), FileSystemCapabilitySupport::Unsupported)
134 }
135
136 #[inline]
138 #[must_use]
139 pub const fn guarantees(&self, capability: FileSystemCapability) -> bool {
140 matches!(self.support(capability), FileSystemCapabilitySupport::Guaranteed)
141 }
142
143 #[inline]
148 #[must_use]
149 pub const fn len(&self) -> usize {
150 (self.conditional | self.guaranteed).count_ones() as usize
151 }
152
153 #[inline]
158 #[must_use]
159 pub const fn is_empty(&self) -> bool {
160 self.conditional == 0 && self.guaranteed == 0
161 }
162
163 #[inline]
168 pub fn iter(&self) -> impl Iterator<Item = FileSystemCapability> + '_ {
169 FileSystemCapability::ALL
170 .iter()
171 .copied()
172 .filter(|capability| self.supports(*capability))
173 }
174
175 #[inline]
177 pub fn iter_with_support(&self) -> impl Iterator<Item = (FileSystemCapability, FileSystemCapabilitySupport)> + '_ {
178 self.iter().map(|capability| (capability, self.support(capability)))
179 }
180
181 #[inline]
192 #[must_use]
193 pub fn missing_dependency(&self) -> Option<(FileSystemCapability, FileSystemCapability)> {
194 CAPABILITY_DEPENDENCIES
195 .iter()
196 .copied()
197 .find(|(capability, dependency)| {
198 let capability_support = self.support(*capability);
199 let dependency_support = self.support(*dependency);
200 matches!(capability_support, FileSystemCapabilitySupport::Conditional)
201 && matches!(dependency_support, FileSystemCapabilitySupport::Unsupported)
202 || matches!(capability_support, FileSystemCapabilitySupport::Guaranteed)
203 && !matches!(dependency_support, FileSystemCapabilitySupport::Guaranteed)
204 })
205 }
206}
207
208impl Default for FileSystemCapabilities {
209 #[inline]
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216impl Debug for FileSystemCapabilities {
217 #[inline]
218 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
219 formatter.debug_map().entries(self.iter_with_support()).finish()
220 }
221}