ndi_sdk_sys/
resolution.rs1use std::fmt::{Debug, Display};
2
3#[derive(Clone, Copy, PartialEq, Eq, Hash)]
4pub struct Resolution {
5 pub x: usize,
6 pub y: usize,
7}
8
9impl Resolution {
10 pub fn new(x: usize, y: usize) -> Self {
14 let res = Resolution { x, y };
15 res.check_is_safe();
16 res
17 }
18
19 pub fn try_new(x: usize, y: usize) -> Option<Self> {
20 if Resolution::is_safe(x, y) {
21 Some(Resolution { x, y })
22 } else {
23 None
24 }
25 }
26
27 pub const fn new_const(x: usize, y: usize) -> Self {
28 assert!(
29 Resolution::is_safe(x, y),
30 "Resolution is not safe (more info is not available in the const version of the constructor)"
31 );
32 Resolution { x, y }
33 }
34
35 pub fn from_i32(x: i32, y: i32) -> Self {
36 let res = Resolution {
37 x: x.try_into()
38 .expect("Invalid x-resolution, failed to cast to usize (x = {x})"),
39 y: y.try_into()
40 .expect("Invalid y-resolution, failed to cast to usize (y = {y})"),
41 };
42 res.check_is_safe();
43 res
44 }
45
46 pub const fn to_i32(&self) -> (i32, i32) {
47 (self.x as i32, self.y as i32)
48 }
49
50 pub fn aspect_ratio(&self) -> f64 {
51 self.x as f64 / self.y as f64
52 }
53
54 pub const fn pixels(&self) -> usize {
55 self.x * self.y
57 }
58
59 fn check_is_safe(&self) {
60 assert!(
61 Resolution::is_safe(self.x, self.x),
62 "Resolution is not safe: {}x{}",
63 self.x,
64 self.y
65 );
66 }
67
68 pub const fn is_safe(x: usize, y: usize) -> bool {
75 const MAX_SAFE_VALUE: usize = i32::MAX as usize;
76 const MAX_PIXEL_BYTES: usize = 8; const MAX_SAFE_PIXELS: usize = MAX_SAFE_VALUE / MAX_PIXEL_BYTES;
78
79 if x == 0 || y == 0 {
80 return false;
81 }
82
83 if x & 0b1 != 0 {
86 return false;
87 }
88
89 if x >= MAX_SAFE_VALUE || y >= MAX_SAFE_VALUE {
90 return false;
91 }
92
93 if let Some(area) = usize::checked_mul(x, y) {
94 area < MAX_SAFE_PIXELS
95 } else {
96 false
97 }
98 }
99}
100
101impl Display for Resolution {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 write!(f, "{}x{}", self.x, self.y)
104 }
105}
106
107impl Debug for Resolution {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 write!(f, "Resolution({}x{})", self.x, self.y)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_resolution_safe() {
119 _ = Resolution::new(1920, 1080);
120 }
121
122 #[test]
123 fn test_resolution_unsafe() {
124 fn assert_unsafe(x: usize, y: usize) {
125 assert!(
126 !Resolution::is_safe(x, y),
127 "Resolution {}x{} should be unsafe",
128 x,
129 y
130 );
131 }
132
133 assert_unsafe(0, 1080);
135 assert_unsafe(1920, 0);
136
137 assert_unsafe(i32::MAX as usize, 2);
139 }
140}