Skip to main content

qubit_fs/metadata/
write_outcome.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//! Write operation outcome.
9
10use crate::metadata::AchievedAtomicity;
11use crate::metadata::NonSensitiveMetadata;
12use crate::metadata::PublicationMethod;
13use crate::metadata::ResourceVersion;
14use crate::metadata::UserMetadata;
15
16/// Outcome returned when a writer is committed.
17///
18/// # Examples
19///
20/// ```rust
21/// use qubit_fs::metadata::{AchievedAtomicity, PublicationMethod, WriteOutcome};
22///
23/// let outcome = WriteOutcome::new(AchievedAtomicity::Atomic, PublicationMethod::Direct);
24/// assert_eq!(AchievedAtomicity::Atomic, outcome.atomicity());
25/// ```
26#[derive(Clone, Debug, PartialEq)]
27pub struct WriteOutcome {
28    /// Number of bytes written when known.
29    bytes_written: Option<u64>,
30    /// Provider version, generation, or ETag when known.
31    version: Option<ResourceVersion>,
32    /// Atomicity actually achieved by publication.
33    atomicity: AchievedAtomicity,
34    /// Concrete publication method that completed the write.
35    method: PublicationMethod,
36    /// Whether data and namespace publication were durably synchronized.
37    durable: bool,
38    /// Provider-native non-sensitive diagnostics.
39    diagnostics: NonSensitiveMetadata,
40}
41
42impl WriteOutcome {
43    /// Creates a write outcome with explicit publication semantics.
44    ///
45    /// # Parameters
46    /// - `atomicity`: Atomicity actually achieved.
47    /// - `method`: Method used to publish the resource.
48    ///
49    /// # Returns
50    /// A write outcome with no byte count, version, or diagnostics.
51    #[inline]
52    #[must_use]
53    pub fn new(atomicity: AchievedAtomicity, method: PublicationMethod) -> Self {
54        Self {
55            bytes_written: None,
56            version: None,
57            atomicity,
58            method,
59            durable: false,
60            diagnostics: NonSensitiveMetadata::new(),
61        }
62    }
63
64    /// Returns the number of bytes accepted by the write session, when known.
65    #[inline]
66    #[must_use]
67    pub const fn bytes_written(&self) -> Option<u64> {
68        self.bytes_written
69    }
70
71    /// Returns the provider version, generation, or ETag when known.
72    #[inline]
73    #[must_use]
74    pub const fn version(&self) -> Option<&ResourceVersion> {
75        self.version.as_ref()
76    }
77
78    /// Returns the atomicity actually achieved by publication.
79    #[inline]
80    #[must_use]
81    pub const fn atomicity(&self) -> AchievedAtomicity {
82        self.atomicity
83    }
84
85    /// Returns the concrete method that published the resource.
86    #[inline]
87    #[must_use]
88    pub const fn method(&self) -> PublicationMethod {
89        self.method
90    }
91
92    /// Returns whether the provider confirmed durable publication.
93    #[inline]
94    #[must_use]
95    pub const fn durable(&self) -> bool {
96        self.durable
97    }
98
99    /// Returns provider-native non-sensitive diagnostics.
100    #[inline]
101    #[must_use]
102    pub const fn diagnostics(&self) -> &NonSensitiveMetadata {
103        &self.diagnostics
104    }
105
106    /// Records the byte count confirmed by the provider.
107    #[inline]
108    #[must_use]
109    pub const fn with_bytes_written(mut self, bytes_written: u64) -> Self {
110        self.bytes_written = Some(bytes_written);
111        self
112    }
113
114    /// Records the provider version, generation, or ETag.
115    #[inline]
116    #[must_use]
117    pub fn with_version(mut self, version: ResourceVersion) -> Self {
118        self.version = Some(version);
119        self
120    }
121
122    /// Records whether data and namespace publication were durably
123    /// synchronized.
124    #[inline]
125    #[must_use]
126    pub const fn with_durable(mut self, durable: bool) -> Self {
127        self.durable = durable;
128        self
129    }
130
131    /// Replaces provider-native diagnostics that have already passed key
132    /// validation.
133    #[inline]
134    #[must_use]
135    pub fn with_diagnostics(mut self, diagnostics: UserMetadata) -> Self {
136        self.diagnostics = NonSensitiveMetadata::from(diagnostics);
137        self
138    }
139}