1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
use crate::AsyncBucketTransferProtocol;
#[cfg(test)]
use crate::LocalFileSystemProtocol;
use space_system::SpaceRootTest;
pub mod bind;
pub mod config;
pub mod init;
mod idmap;
mod space;
/// Represents the state of a bucket in the transfer protocol.
///
/// # Variants
///
/// * `Uninit` - The bucket has not been initialized. This is the default state.
/// **Warning:** Most mutation methods (e.g., `set_extra_info`, `remove_extra_info`) will **panic**
/// when called on an `Uninit` bucket. Always ensure the bucket is in a `Local` or `Remote` state
/// before attempting to modify its `extra_info`.
///
/// * `Local` - The bucket is on the local side of the transfer, with optional extra information.
///
/// * `Remote` - The bucket is on the remote side of the transfer, with optional extra information.
#[derive(Default, Clone, SpaceRootTest)]
#[space_root_test_generic(LocalFileSystemProtocol)]
pub enum Bucket<Protocol>
where
Protocol: AsyncBucketTransferProtocol + Send + Sync,
{
#[default]
Uninit,
Local {
extra_info: Option<Protocol::ExtraInfo>,
},
Remote {
extra_info: Option<Protocol::ExtraInfo>,
},
}
impl<Protocol: AsyncBucketTransferProtocol + Send + Sync> Bucket<Protocol> {
/// Creates a new `Bucket::Local`
pub fn new_local() -> Self {
Self::Local { extra_info: None }
}
/// Creates a new `Bucket::Local` with extra information.
pub fn local_with_extra_info(extra_info: Protocol::ExtraInfo) -> Self {
Self::Local {
extra_info: Some(extra_info),
}
}
/// Creates a new `Bucket::Remote`
pub fn new_remote() -> Self {
Self::Remote { extra_info: None }
}
/// Creates a new `Bucket::Remote` with extra information.
pub fn remote_with_extra_info(extra_info: Protocol::ExtraInfo) -> Self {
Self::Remote {
extra_info: Some(extra_info),
}
}
/// Returns a mutable reference to the extra_info field regardless of variant.
fn extra_info_mut(&mut self) -> &mut Option<Protocol::ExtraInfo> {
match self {
Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
Self::Uninit => panic!("Cannot access extra_info on an Uninit bucket"),
}
}
/// Sets extra info on an existing bucket, returning the previous value if any.
pub fn set_extra_info(
&mut self,
extra_info: Protocol::ExtraInfo,
) -> Option<Protocol::ExtraInfo> {
self.extra_info_mut().replace(extra_info)
}
/// Removes extra info from the bucket, returning it if present.
pub fn remove_extra_info(&mut self) -> Option<Protocol::ExtraInfo> {
self.extra_info_mut().take()
}
/// Checks if the bucket has extra information.
pub fn has_extra_info(&self) -> bool {
match self {
Self::Local { extra_info } | Self::Remote { extra_info } => extra_info.is_some(),
Self::Uninit => false,
}
}
/// Gets a reference to the extra info, if present.
pub fn extra_info(&self) -> Option<&Protocol::ExtraInfo> {
match self {
Self::Local { extra_info } | Self::Remote { extra_info } => extra_info.as_ref(),
Self::Uninit => None,
}
}
/// Returns true if this is a local bucket.
pub fn is_local(&self) -> bool {
matches!(self, Self::Local { .. })
}
/// Returns true if this is a remote bucket.
pub fn is_remote(&self) -> bool {
matches!(self, Self::Remote { .. })
}
/// Returns true if this bucket is uninitialized.
pub fn is_uninit(&self) -> bool {
matches!(self, Self::Uninit)
}
/// Converts the bucket to a Remote variant, keeping extra_info if present.
pub fn force_to_remote(self) -> Self {
let extra_info = match self {
Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
Self::Uninit => None,
};
Self::Remote { extra_info }
}
/// Converts the bucket to a Local variant, keeping extra_info if present.
pub fn force_to_local(self) -> Self {
let extra_info = match self {
Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
Self::Uninit => None,
};
Self::Local { extra_info }
}
}
|