use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum TransformType {
ResizeImage,
CropImage,
Normalize,
ToGrayscale,
GaussianBlur,
Brightness,
Contrast,
Rotate,
FlipHorizontal,
FlipVertical,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum TransformConfig {
ResizeImage {
shorter_side: Option<u32>,
longer_side: Option<u32>,
width: Option<u32>,
height: Option<u32>,
maintain_aspect_ratio: Option<bool>,
interpolation: Option<String>,
},
CropImage {
width: u32,
height: u32,
mode: Option<String>,
},
Normalize {
mean: Vec<f32>,
std: Vec<f32>,
},
ToGrayscale,
GaussianBlur {
sigma: f32,
},
Brightness {
factor: f32,
},
Contrast {
factor: f32,
},
Rotate {
angle: f32,
},
FlipHorizontal,
FlipVertical,
}
#[derive(Debug)]
pub struct TransformRegistry {
transforms: Vec<(TransformType, TransformConfig)>,
}
impl TransformRegistry {
pub fn new() -> Self {
Self {
transforms: Vec::new(),
}
}
pub fn add(&mut self, transform_type: TransformType, config: TransformConfig) {
self.transforms.push((transform_type, config));
}
pub fn remove(&mut self, transform_type: &TransformType) -> usize {
let initial_len = self.transforms.len();
self.transforms.retain(|(t, _)| t != transform_type);
initial_len - self.transforms.len()
}
pub fn len(&self) -> usize {
self.transforms.len()
}
pub fn is_empty(&self) -> bool {
self.transforms.is_empty()
}
pub fn clear(&mut self) {
self.transforms.clear();
}
pub fn iter(&self) -> std::slice::Iter<'_, (TransformType, TransformConfig)> {
self.transforms.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, (TransformType, TransformConfig)> {
self.transforms.iter_mut()
}
pub fn contains(&self, transform_type: &TransformType) -> bool {
self.transforms.iter().any(|(t, _)| t == transform_type)
}
pub fn get_all(&self, transform_type: &TransformType) -> Vec<&TransformConfig> {
self.transforms
.iter()
.filter_map(|(t, config)| {
if t == transform_type {
Some(config)
} else {
None
}
})
.collect()
}
pub fn get_first(&self, transform_type: &TransformType) -> Option<&TransformConfig> {
self.transforms.iter().find_map(|(t, config)| {
if t == transform_type {
Some(config)
} else {
None
}
})
}
}
impl IntoIterator for TransformRegistry {
type Item = (TransformType, TransformConfig);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.transforms.into_iter()
}
}
impl<'a> IntoIterator for &'a TransformRegistry {
type Item = &'a (TransformType, TransformConfig);
type IntoIter = std::slice::Iter<'a, (TransformType, TransformConfig)>;
fn into_iter(self) -> Self::IntoIter {
self.transforms.iter()
}
}
impl<'a> IntoIterator for &'a mut TransformRegistry {
type Item = &'a mut (TransformType, TransformConfig);
type IntoIter = std::slice::IterMut<'a, (TransformType, TransformConfig)>;
fn into_iter(self) -> Self::IntoIter {
self.transforms.iter_mut()
}
}
impl Default for TransformRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_transform_registry_add() {
let mut registry = TransformRegistry::new();
registry.add(
TransformType::ResizeImage,
TransformConfig::ResizeImage {
width: Some(224),
height: Some(224),
shorter_side: None,
longer_side: None,
maintain_aspect_ratio: Some(false),
interpolation: None,
},
);
assert_eq!(registry.len(), 1);
assert!(!registry.is_empty());
}
#[test]
fn test_transform_registry_remove() {
let mut registry = TransformRegistry::new();
registry.add(TransformType::ResizeImage, TransformConfig::ToGrayscale);
registry.add(TransformType::ToGrayscale, TransformConfig::ToGrayscale);
let removed = registry.remove(&TransformType::ToGrayscale);
assert_eq!(removed, 1);
assert_eq!(registry.len(), 1);
}
#[test]
fn test_transform_registry_contains() {
let mut registry = TransformRegistry::new();
registry.add(TransformType::ResizeImage, TransformConfig::ToGrayscale);
assert!(registry.contains(&TransformType::ResizeImage));
assert!(!registry.contains(&TransformType::ToGrayscale));
}
#[test]
fn test_transform_registry_clear() {
let mut registry = TransformRegistry::new();
registry.add(TransformType::ResizeImage, TransformConfig::ToGrayscale);
registry.add(TransformType::ToGrayscale, TransformConfig::ToGrayscale);
registry.clear();
assert_eq!(registry.len(), 0);
assert!(registry.is_empty());
}
}