ip/any/prefix/
len.rs

1use core::fmt;
2
3#[cfg(any(test, feature = "arbitrary"))]
4use proptest::{
5    arbitrary::{any, Arbitrary},
6    prop_oneof,
7    strategy::{BoxedStrategy, Strategy},
8};
9
10use super::delegate;
11use crate::{
12    concrete::{self, Ipv4, Ipv6},
13    traits, Error,
14};
15
16/// The length of either an IPv4 or IPv6 prefix.
17///
18/// # Examples
19///
20/// ``` rust
21/// use ip::{traits::Prefix as _, Any, Prefix, PrefixLength};
22///
23/// let prefix = "2001:db8::/32".parse::<Prefix<Any>>()?;
24///
25/// assert!(matches!(prefix.prefix_len(), PrefixLength::<Any>::Ipv6(_)));
26/// # Ok::<(), ip::Error>(())
27/// ```
28#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd)]
29pub enum Length {
30    /// IPv4 prefix length variant.
31    Ipv4(concrete::PrefixLength<Ipv4>),
32    /// IPv6 prefix length variant.
33    Ipv6(concrete::PrefixLength<Ipv6>),
34}
35
36impl traits::PrefixLength for Length {
37    fn increment(self) -> Result<Self, Error> {
38        match self {
39            Self::Ipv4(length) => length.increment().map(Self::from),
40            Self::Ipv6(length) => length.increment().map(Self::from),
41        }
42    }
43
44    fn decrement(self) -> Result<Self, Error> {
45        match self {
46            Self::Ipv4(length) => length.decrement().map(Self::from),
47            Self::Ipv6(length) => length.decrement().map(Self::from),
48        }
49    }
50}
51
52impl From<concrete::PrefixLength<Ipv4>> for Length {
53    fn from(length: concrete::PrefixLength<Ipv4>) -> Self {
54        Self::Ipv4(length)
55    }
56}
57
58impl From<concrete::PrefixLength<Ipv6>> for Length {
59    fn from(length: concrete::PrefixLength<Ipv6>) -> Self {
60        Self::Ipv6(length)
61    }
62}
63
64impl AsRef<u8> for Length {
65    delegate! {
66        fn as_ref(&self) -> &u8;
67    }
68}
69
70impl fmt::Display for Length {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            Self::Ipv4(len) => len.fmt(f),
74            Self::Ipv6(len) => len.fmt(f),
75        }
76    }
77}
78
79#[cfg(any(test, feature = "arbitrary"))]
80impl Arbitrary for Length {
81    type Parameters = ();
82    type Strategy = BoxedStrategy<Self>;
83
84    fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
85        prop_oneof![
86            any::<concrete::PrefixLength<Ipv4>>().prop_map(Self::Ipv4),
87            any::<concrete::PrefixLength<Ipv6>>().prop_map(Self::Ipv6),
88        ]
89        .boxed()
90    }
91}