forma_render/utils/
order.rs

1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}