surpass/
order.rs

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