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