blob: f01a197495ca074cb1f38737e31777f405e03ab8 [file] [log] [blame]
use crate::*;
/// IEEE 802.1Q VLAN Tagging Header (can be single or double tagged).
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VlanHeader {
/// IEEE 802.1Q VLAN Tagging Header
Single(SingleVlanHeader),
/// IEEE 802.1Q double VLAN Tagging Header
Double(DoubleVlanHeader),
}
impl VlanHeader {
/// All ether types that identify a vlan header.
pub const VLAN_ETHER_TYPES: [EtherType; 3] = [
ether_type::VLAN_TAGGED_FRAME,
ether_type::PROVIDER_BRIDGING,
ether_type::VLAN_DOUBLE_TAGGED_FRAME,
];
/// Write the IEEE 802.1Q VLAN single or double tagging header
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[inline]
pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
use VlanHeader::*;
match &self {
Single(header) => header.write(writer),
Double(header) => header.write(writer),
}
}
/// Returns the ether type of the next header after the vlan header(s).
#[inline]
pub fn next_header(&self) -> EtherType {
match self {
VlanHeader::Single(s) => s.ether_type,
VlanHeader::Double(d) => d.inner.ether_type,
}
}
/// Length of the serialized header(s) in bytes.
#[inline]
pub fn header_len(&self) -> usize {
use VlanHeader::*;
match &self {
Single(_) => SingleVlanHeader::LEN,
Double(_) => DoubleVlanHeader::LEN,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::test_gens::*;
use alloc::{format, vec::Vec};
use proptest::prelude::*;
#[test]
fn constants() {
use ether_type::*;
use VlanHeader as V;
assert_eq!(3, V::VLAN_ETHER_TYPES.len());
assert_eq!(VLAN_TAGGED_FRAME, V::VLAN_ETHER_TYPES[0]);
assert_eq!(PROVIDER_BRIDGING, V::VLAN_ETHER_TYPES[1]);
assert_eq!(VLAN_DOUBLE_TAGGED_FRAME, V::VLAN_ETHER_TYPES[2]);
}
proptest! {
#[test]
fn clone_eq(
single in vlan_single_any(),
double in vlan_double_any(),
) {
// single eq
{
let value = VlanHeader::Single(single.clone());
assert_eq!(value, value.clone());
}
// double
{
let value = VlanHeader::Double(double);
assert_eq!(value, value.clone());
}
}
}
proptest! {
#[test]
fn dbg(
single in vlan_single_any(),
double in vlan_double_any(),
) {
// single
{
let value = VlanHeader::Single(single.clone());
assert_eq!(
&format!(
"Single({:?})",
single
),
&format!("{:?}", value)
);
}
// double
{
let value = VlanHeader::Double(double.clone());
assert_eq!(
&format!(
"Double({:?})",
double
),
&format!("{:?}", value)
);
}
}
}
proptest! {
#[test]
fn next_header(
single in vlan_single_any(),
double in vlan_double_any(),
) {
// single
{
let value = VlanHeader::Single(single.clone());
assert_eq!(value.next_header(), single.ether_type);
}
// double
{
let value = VlanHeader::Double(double.clone());
assert_eq!(value.next_header(), double.inner.ether_type);
}
}
}
proptest! {
#[test]
fn header_len(
single in vlan_single_any(),
double in vlan_double_any(),
) {
// single
assert_eq!(
SingleVlanHeader::LEN,
VlanHeader::Single(single.clone()).header_len()
);
// double
assert_eq!(
DoubleVlanHeader::LEN,
VlanHeader::Double(double.clone()).header_len()
);
}
}
proptest! {
#[test]
fn write(
single in vlan_single_any(),
double in vlan_double_any(),
) {
// single
{
let expected = {
let mut buffer = Vec::with_capacity(single.header_len());
single.write(&mut buffer).unwrap();
buffer
};
let actual = {
let mut buffer = Vec::with_capacity(single.header_len());
VlanHeader::Single(single.clone()).write(&mut buffer).unwrap();
buffer
};
assert_eq!(expected, actual);
}
// double
{
let expected = {
let mut buffer = Vec::with_capacity(double.header_len());
double.write(&mut buffer).unwrap();
buffer
};
let actual = {
let mut buffer = Vec::with_capacity(double.header_len());
VlanHeader::Double(double.clone()).write(&mut buffer).unwrap();
buffer
};
assert_eq!(expected, actual);
}
}
}
}