mod azdls;
mod gcs;
mod oss;
mod s3;
use std::collections::HashMap;
pub use azdls::*;
pub use gcs::*;
pub use oss::*;
pub use s3::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct StorageConfig {
props: HashMap<String, String>,
}
impl StorageConfig {
pub fn new() -> Self {
Self {
props: HashMap::new(),
}
}
pub fn from_props(props: HashMap<String, String>) -> Self {
Self { props }
}
pub fn props(&self) -> &HashMap<String, String> {
&self.props
}
pub fn get(&self, key: &str) -> Option<&String> {
self.props.get(key)
}
pub fn with_prop(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.props.insert(key.into(), value.into());
self
}
pub fn with_props(
mut self,
props: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.props
.extend(props.into_iter().map(|(k, v)| (k.into(), v.into())));
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_storage_config_new() {
let config = StorageConfig::new();
assert!(config.props().is_empty());
}
#[test]
fn test_storage_config_from_props() {
let props = HashMap::from([
("region".to_string(), "us-east-1".to_string()),
("bucket".to_string(), "my-bucket".to_string()),
]);
let config = StorageConfig::from_props(props.clone());
assert_eq!(config.props(), &props);
}
#[test]
fn test_storage_config_default() {
let config = StorageConfig::default();
assert!(config.props().is_empty());
}
#[test]
fn test_storage_config_get() {
let config = StorageConfig::new().with_prop("region", "us-east-1");
assert_eq!(config.get("region"), Some(&"us-east-1".to_string()));
assert_eq!(config.get("nonexistent"), None);
}
#[test]
fn test_storage_config_with_prop() {
let config = StorageConfig::new()
.with_prop("region", "us-east-1")
.with_prop("bucket", "my-bucket");
assert_eq!(config.get("region"), Some(&"us-east-1".to_string()));
assert_eq!(config.get("bucket"), Some(&"my-bucket".to_string()));
}
#[test]
fn test_storage_config_with_props() {
let additional_props = vec![("key1", "value1"), ("key2", "value2")];
let config = StorageConfig::new().with_props(additional_props);
assert_eq!(config.get("key1"), Some(&"value1".to_string()));
assert_eq!(config.get("key2"), Some(&"value2".to_string()));
}
#[test]
fn test_storage_config_clone() {
let config = StorageConfig::new().with_prop("region", "us-east-1");
let cloned = config.clone();
assert_eq!(config, cloned);
assert_eq!(cloned.get("region"), Some(&"us-east-1".to_string()));
}
#[test]
fn test_storage_config_serialization_roundtrip() {
let config = StorageConfig::new()
.with_prop("region", "us-east-1")
.with_prop("bucket", "my-bucket");
let serialized = serde_json::to_string(&config).unwrap();
let deserialized: StorageConfig = serde_json::from_str(&serialized).unwrap();
assert_eq!(config, deserialized);
}
#[test]
fn test_storage_config_clone_independence() {
let original = StorageConfig::new().with_prop("region", "us-east-1");
let mut cloned = original.clone();
cloned = cloned.with_prop("region", "eu-west-1");
cloned = cloned.with_prop("new_key", "new_value");
assert_eq!(original.get("region"), Some(&"us-east-1".to_string()));
assert_eq!(original.get("new_key"), None);
assert_eq!(cloned.get("region"), Some(&"eu-west-1".to_string()));
assert_eq!(cloned.get("new_key"), Some(&"new_value".to_string()));
}
#[test]
fn test_storage_config_from_props_empty() {
let config = StorageConfig::from_props(HashMap::new());
assert!(config.props().is_empty());
}
#[test]
fn test_storage_config_serialization_empty() {
let config = StorageConfig::new();
let serialized = serde_json::to_string(&config).unwrap();
let deserialized: StorageConfig = serde_json::from_str(&serialized).unwrap();
assert_eq!(config, deserialized);
assert!(deserialized.props().is_empty());
}
}