use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum OptPort {
#[default]
Unset,
Empty,
Set(u16),
}
impl OptPort {
#[must_use]
#[inline]
pub const fn as_u16(self) -> Option<u16> {
match self {
Self::Set(n) => Some(n),
Self::Unset | Self::Empty => None,
}
}
#[must_use]
#[inline]
pub const fn is_explicit(self) -> bool {
!matches!(self, Self::Unset)
}
#[must_use]
#[inline]
pub const fn is_empty(self) -> bool {
matches!(self, Self::Empty)
}
#[must_use]
#[inline]
pub const fn is_unset(self) -> bool {
matches!(self, Self::Unset)
}
}
impl From<u16> for OptPort {
#[inline]
fn from(n: u16) -> Self {
Self::Set(n)
}
}
impl From<Option<u16>> for OptPort {
#[inline]
fn from(opt: Option<u16>) -> Self {
match opt {
Some(n) => Self::Set(n),
None => Self::Unset,
}
}
}
impl From<OptPort> for Option<u16> {
#[inline]
fn from(p: OptPort) -> Self {
p.as_u16()
}
}
impl fmt::Display for OptPort {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unset => Ok(()),
Self::Empty => f.write_str(":"),
Self::Set(n) => write!(f, ":{n}"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn as_u16_collapses_unset_and_empty() {
assert_eq!(OptPort::Unset.as_u16(), None);
assert_eq!(OptPort::Empty.as_u16(), None);
assert_eq!(OptPort::Set(8080).as_u16(), Some(8080));
}
#[test]
fn distinct_under_eq_hash_ord() {
use crate::test_hash::hash;
assert_ne!(OptPort::Unset, OptPort::Empty);
assert_ne!(OptPort::Unset, OptPort::Set(0));
assert_ne!(OptPort::Empty, OptPort::Set(0));
assert_ne!(hash(&OptPort::Unset), hash(&OptPort::Empty));
assert!(OptPort::Unset < OptPort::Empty);
assert!(OptPort::Empty < OptPort::Set(0));
assert!(OptPort::Set(0) < OptPort::Set(1));
}
#[test]
fn display_matches_wire_form() {
assert_eq!(OptPort::Unset.to_string(), "");
assert_eq!(OptPort::Empty.to_string(), ":");
assert_eq!(OptPort::Set(8080).to_string(), ":8080");
}
#[test]
fn from_conversions() {
assert_eq!(OptPort::from(8080u16), OptPort::Set(8080));
assert_eq!(OptPort::from(None::<u16>), OptPort::Unset);
assert_eq!(OptPort::from(Some(8080u16)), OptPort::Set(8080));
let back: Option<u16> = OptPort::Empty.into();
assert_eq!(back, None);
}
}