forma_render/utils/
order.rs1use std::{convert::TryFrom, error::Error, fmt, num::NonZeroU32};
16
17use crate::consts;
18
19#[derive(Debug, Eq, PartialEq)]
20pub enum OrderError {
21 ExceededLayerLimit,
22}
23
24impl fmt::Display for OrderError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 write!(f, "exceeded layer limit ({})", consts::LAYER_LIMIT)
27 }
28}
29
30impl Error for OrderError {}
31
32#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
33pub struct Order(NonZeroU32);
34
35impl Default for Order {
36 fn default() -> Self {
37 match Self::new(0) {
38 Ok(order) => order,
39 Err(_) => panic!("0 is smaller than Order::MAX"),
40 }
41 }
42}
43
44impl Order {
45 pub const MAX: Self = Self(
46 match NonZeroU32::new(consts::LAYER_LIMIT as u32 ^ u32::MAX) {
47 Some(val) => val,
48 None => panic!("LAYER_LIMIT is smaller than u32::MAX"),
49 },
50 );
51
52 pub const fn as_u32(&self) -> u32 {
53 self.0.get() ^ u32::MAX
54 }
55
56 pub const fn new(order: u32) -> Result<Self, OrderError> {
57 if order > Self::MAX.as_u32() {
58 Err(OrderError::ExceededLayerLimit)
59 } else {
60 Ok(Self(match NonZeroU32::new(order ^ u32::MAX) {
61 Some(val) => val,
62 None => panic!("Order::MAX is smaller than u32::MAX"),
63 }))
64 }
65 }
66}
67
68impl fmt::Debug for Order {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 f.debug_tuple("Order").field(&self.as_u32()).finish()
71 }
72}
73
74impl From<Order> for u32 {
75 fn from(order: Order) -> Self {
76 order.as_u32()
77 }
78}
79
80impl TryFrom<u32> for Order {
81 type Error = OrderError;
82
83 fn try_from(order: u32) -> Result<Self, OrderError> {
84 Self::new(order)
85 }
86}
87
88impl TryFrom<usize> for Order {
89 type Error = OrderError;
90
91 fn try_from(order: usize) -> Result<Self, OrderError> {
92 u32::try_from(order)
93 .map_err(|_| OrderError::ExceededLayerLimit)
94 .and_then(Self::try_from)
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn wrong_u32_order_value() {
104 let order = Order::MAX.as_u32() + 1;
105
106 assert_eq!(Order::try_from(order), Err(OrderError::ExceededLayerLimit));
107 }
108
109 #[test]
110 fn wrong_usize_order_values() {
111 let order = (Order::MAX.as_u32() + 1) as usize;
112
113 assert_eq!(Order::try_from(order), Err(OrderError::ExceededLayerLimit));
114
115 let order = u64::MAX as usize;
116
117 assert_eq!(Order::try_from(order), Err(OrderError::ExceededLayerLimit));
118 }
119
120 #[test]
121 fn correct_order_value() {
122 let order_value = Order::MAX.as_u32();
123 let order = Order::try_from(order_value);
124
125 assert_eq!(
126 order,
127 Ok(Order(
128 NonZeroU32::new(order_value as u32 ^ u32::MAX).unwrap()
129 ))
130 );
131 }
132}