mm_client_common/
pixel_scale.rs

1// Copyright 2024 Colin Marc <hi@colinmarc.com>
2//
3// SPDX-License-Identifier: MIT
4
5use mm_protocol as protocol;
6
7use crate::validation::*;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Record)]
10pub struct PixelScale {
11    numerator: u32,
12    denominator: u32,
13}
14
15impl PixelScale {
16    pub const ONE: Self = Self {
17        numerator: 1,
18        denominator: 1,
19    };
20
21    pub fn new(numerator: u32, denominator: u32) -> Self {
22        Self {
23            numerator,
24            denominator,
25        }
26    }
27
28    pub fn is_fractional(&self) -> bool {
29        (self.numerator % self.denominator) != 0
30    }
31
32    pub fn round_up(self) -> Self {
33        Self {
34            numerator: self.numerator.next_multiple_of(self.denominator) / self.denominator,
35            denominator: 1,
36        }
37    }
38}
39
40impl std::fmt::Display for PixelScale {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        write!(f, "{:.1}", self.numerator as f64 / self.denominator as f64)
43    }
44}
45
46impl TryFrom<protocol::PixelScale> for PixelScale {
47    type Error = ValidationError;
48
49    fn try_from(scale: protocol::PixelScale) -> Result<Self, Self::Error> {
50        if scale.denominator == 0 && scale.numerator != 0 {
51            Ok(Self::ONE)
52        } else if scale.denominator == 0 || scale.numerator == 0 {
53            Err(ValidationError::Required("denominator".to_string()))
54        } else {
55            Ok(Self {
56                numerator: scale.numerator,
57                denominator: scale.denominator,
58            })
59        }
60    }
61}
62
63impl From<PixelScale> for protocol::PixelScale {
64    fn from(scale: PixelScale) -> Self {
65        Self {
66            numerator: scale.numerator,
67            denominator: scale.denominator,
68        }
69    }
70}