ethertype/
lib.rs

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
//! A crate providing the [`EtherType`] type for representing IEEE 802 EtherType values.
//!
//! The [`consts`] module contains the most common EtherTypes, the descriptions of which can be
//! obtained using [`EtherType::description`].
//!
//! Additionally, descriptions from
//! [IANA](https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml) can be obtained
//! with [`EtherType::iana_description`]. Protocol descriptions and the names of the organizations
//! that registered them sourced from the
//! [IEEE Registration Authority](http://standards.ieee.org/develop/regauth) can be obtained with
//! [`EtherType::ieee_description`] and [`EtherType::ieee_organization`] respectively.

#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]

use core::{fmt, str::FromStr};

use error::ParseEtherTypeError;

pub mod consts;
pub mod error;

#[cfg_attr(docsrs, doc(cfg(feature = "ieee")))]
#[cfg(feature = "ieee")]
mod ieee;

#[cfg_attr(docsrs, doc(cfg(feature = "iana")))]
#[cfg(feature = "iana")]
mod iana;

#[cfg_attr(docsrs, doc(cfg(feature = "desc")))]
#[cfg(feature = "desc")]
mod desc;

#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
#[cfg(feature = "serde")]
mod serde;

/// The EtherType field in an Ethernet header, as specified in IEEE 802.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct EtherType(pub u16);

impl From<u16> for EtherType {
    fn from(value: u16) -> Self {
        Self(value)
    }
}

impl From<EtherType> for u16 {
    fn from(value: EtherType) -> Self {
        value.0
    }
}

impl fmt::Display for EtherType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{:04x}", self.0)
    }
}

impl FromStr for EtherType {
    type Err = ParseEtherTypeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.len() != 4 {
            return Err(ParseEtherTypeError::InvalidLength);
        }

        u16::from_str_radix(s, 16)
            .map(EtherType)
            .map_err(ParseEtherTypeError::ParseInt)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[cfg(feature = "std")]
    fn display() {
        let ether_type = EtherType(0x0123);
        assert_eq!("0123", ether_type.to_string())
    }

    #[test]
    fn from_str() {
        assert_eq!(EtherType(0x0123), "0123".parse::<EtherType>().unwrap());
    }

    #[test]
    fn from_str_length_error() {
        assert_eq!(
            Err(ParseEtherTypeError::InvalidLength),
            "123".parse::<EtherType>()
        );
    }
}