1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
6pub enum ViewportOrientation {
7 Portrait,
8 Landscape,
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
13pub enum Density {
14 Compact,
15 Comfortable,
16 Spacious,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
21pub enum ViewportClass {
22 Xs,
23 Sm,
24 Md,
25 Lg,
26 Xl,
27 Xxl,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
32pub struct DisplayScale(u32);
33
34impl DisplayScale {
35 pub fn from_milli(value: u32) -> Self {
36 Self(value)
37 }
38
39 pub fn one() -> Self {
40 Self(1_000)
41 }
42
43 pub fn milli(self) -> u32 {
44 self.0
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
50pub struct ViewportSize {
51 width: u32,
52 height: u32,
53}
54
55impl ViewportSize {
56 pub fn new(width: u32, height: u32) -> Self {
57 Self { width, height }
58 }
59
60 pub fn width(self) -> u32 {
61 self.width
62 }
63
64 pub fn height(self) -> u32 {
65 self.height
66 }
67
68 pub fn orientation(self) -> ViewportOrientation {
69 if self.width >= self.height {
70 ViewportOrientation::Landscape
71 } else {
72 ViewportOrientation::Portrait
73 }
74 }
75
76 pub fn class(self) -> ViewportClass {
77 match self.width {
78 0..=479 => ViewportClass::Xs,
79 480..=767 => ViewportClass::Sm,
80 768..=1023 => ViewportClass::Md,
81 1024..=1279 => ViewportClass::Lg,
82 1280..=1535 => ViewportClass::Xl,
83 _ => ViewportClass::Xxl,
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::{Density, DisplayScale, ViewportClass, ViewportOrientation, ViewportSize};
91
92 #[test]
93 fn classifies_viewport_size() {
94 let phone = ViewportSize::new(390, 844);
95 let desktop = ViewportSize::new(1440, 900);
96
97 assert_eq!(phone.orientation(), ViewportOrientation::Portrait);
98 assert_eq!(phone.class(), ViewportClass::Xs);
99 assert_eq!(desktop.orientation(), ViewportOrientation::Landscape);
100 assert_eq!(desktop.class(), ViewportClass::Xl);
101 }
102
103 #[test]
104 fn stores_density_and_scale() {
105 let scale = DisplayScale::from_milli(1_250);
106
107 assert_eq!(Density::Comfortable, Density::Comfortable);
108 assert_eq!(DisplayScale::one().milli(), 1_000);
109 assert_eq!(scale.milli(), 1_250);
110 }
111}