use std::collections::BTreeMap;
use serde_json::{Value, json};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ResizeTransform {
pub width: u32,
pub height: u32,
}
impl ResizeTransform {
#[must_use]
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CropTransform {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
}
impl CropTransform {
#[must_use]
pub const fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
Self {
x,
y,
width,
height,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ImageTransformations {
pub resize: Option<ResizeTransform>,
pub crop: Option<CropTransform>,
pub format: Option<String>,
}
impl ImageTransformations {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn resize(mut self, width: u32, height: u32) -> Self {
self.resize = Some(ResizeTransform::new(width, height));
self
}
#[must_use]
pub fn crop(mut self, x: u32, y: u32, width: u32, height: u32) -> Self {
self.crop = Some(CropTransform::new(x, y, width, height));
self
}
#[must_use]
pub fn format(mut self, format: impl Into<String>) -> Self {
self.format = Some(format.into());
self
}
#[must_use]
pub fn to_map(&self) -> BTreeMap<String, Value> {
let mut transformations = BTreeMap::new();
if let Some(resize) = self.resize {
transformations.insert(
"resize".to_owned(),
json!({"width": resize.width, "height": resize.height}),
);
}
if let Some(crop) = self.crop {
transformations.insert(
"crop".to_owned(),
json!({
"x": crop.x,
"y": crop.y,
"width": crop.width,
"height": crop.height,
}),
);
}
if let Some(format) = &self.format {
transformations.insert("format".to_owned(), Value::String(format.clone()));
}
transformations
}
}
impl From<ImageTransformations> for BTreeMap<String, Value> {
fn from(value: ImageTransformations) -> Self {
value.to_map()
}
}
impl From<&ImageTransformations> for BTreeMap<String, Value> {
fn from(value: &ImageTransformations) -> Self {
value.to_map()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resize_and_crop_transformations_convert_to_variant_map() {
let transformations = ImageTransformations::new()
.resize(100, 200)
.crop(10, 20, 80, 160)
.format("png")
.to_map();
assert_eq!(
transformations.get("resize"),
Some(&json!({"width": 100, "height": 200})),
);
assert_eq!(
transformations.get("crop"),
Some(&json!({"x": 10, "y": 20, "width": 80, "height": 160})),
);
assert_eq!(
transformations.get("format"),
Some(&Value::String("png".to_owned()))
);
}
#[test]
fn empty_transformations_produce_empty_map() {
assert!(ImageTransformations::new().to_map().is_empty());
}
}