use crate::AsyncBucketTransferProtocol; #[cfg(test)] use crate::LocalFileSystemProtocol; use space_system::SpaceRootTest; mod init; // pub use init::*; 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 where Protocol: AsyncBucketTransferProtocol + Send + Sync, { #[default] Uninit, Local { extra_info: Option, }, Remote { extra_info: Option, }, } impl Bucket { /// 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 { 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 { 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 { 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 } } }