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
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::{error::Error, fmt, num::NonZeroU32};

use crate::LAYER_LIMIT;

#[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 ({})", 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(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())));
    }
}