use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Copy, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Size {
Pixel(i32),
Ratio(f32),
}
impl Size {
pub fn into_absolute(self, whole: u32) -> i32 {
match self {
Size::Pixel(x) => x,
Size::Ratio(x) => (whole as f32 * x.abs()).round() as i32,
}
}
}
#[cfg(test)]
mod tests {
use super::Size;
#[test]
fn absolute_size_into_absolute_stays_same() {
let i = 256i32;
let size = Size::Pixel(i);
let absolute = size.into_absolute(1000);
assert_eq!(absolute, i);
}
#[test]
fn relative_size_into_absolute() {
let size = Size::Ratio(0.6);
let absolute = size.into_absolute(1000);
assert_eq!(absolute, 600);
}
#[test]
fn relative_size_of_small_whole_is_rounded() {
let size = Size::Ratio(0.6);
let absolute = size.into_absolute(1);
assert_eq!(absolute, 1);
}
#[test]
fn relative_size_of_zero_doesnt_panic() {
let size = Size::Ratio(0.6);
let absolute = size.into_absolute(0);
assert_eq!(absolute, 0);
}
#[test]
fn negative_relative_size_must_return_same_as_positive() {
let whole = 1000;
let pos_ratio = Size::Ratio(0.6);
let neg_ratio = Size::Ratio(-0.6);
let pos_absolute = pos_ratio.into_absolute(whole);
let neg_absolute = neg_ratio.into_absolute(whole);
assert_eq!(pos_absolute, neg_absolute);
}
#[test]
fn relative_size_into_absolute_is_rounded() {
let size = Size::Ratio(0.5);
let absolute = size.into_absolute(33);
assert_eq!(absolute, 17);
}
}