use super::super::*;
use std::io;
use std::slice::from_raw_parts;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VlanHeader {
Single(SingleVlanHeader),
Double(DoubleVlanHeader)
}
impl VlanHeader {
pub const VLAN_ETHER_TYPES: [u16;3] = [
ether_type::VLAN_TAGGED_FRAME,
ether_type::PROVIDER_BRIDGING,
ether_type::VLAN_DOUBLE_TAGGED_FRAME,
];
#[inline]
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), WriteError> {
use VlanHeader::*;
match &self {
Single(header) => header.write(writer),
Double(header) => header.write(writer),
}
}
#[inline]
pub fn header_len(&self) -> usize {
use VlanHeader::*;
match &self {
Single(_) => SingleVlanHeader::SERIALIZED_SIZE,
Double(_) => DoubleVlanHeader::SERIALIZED_SIZE,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VlanSlice<'a> {
SingleVlan(SingleVlanHeaderSlice<'a>),
DoubleVlan(DoubleVlanHeaderSlice<'a>),
}
impl<'a> VlanSlice<'a> {
#[inline]
pub fn to_header(&self) -> VlanHeader {
use crate::VlanHeader::*;
use crate::VlanSlice::*;
match self {
SingleVlan(value) => Single(value.to_header()),
DoubleVlan(value) => Double(value.to_header())
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct SingleVlanHeader {
pub priority_code_point: u8,
pub drop_eligible_indicator: bool,
pub vlan_identifier: u16,
pub ether_type: u16,
}
impl SerializedSize for SingleVlanHeader {
const SERIALIZED_SIZE: usize = 4;
}
impl SingleVlanHeader {
#[deprecated(
since = "0.10.1",
note = "Use SingleVlanHeader::from_slice instead."
)]
#[inline]
pub fn read_from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), ReadError> {
SingleVlanHeader::from_slice(slice)
}
#[inline]
pub fn from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), ReadError> {
Ok((
SingleVlanHeaderSlice::from_slice(slice)?.to_header(),
&slice[SingleVlanHeader::SERIALIZED_SIZE .. ]
))
}
#[inline]
pub fn from_bytes(bytes: [u8;4]) -> SingleVlanHeader {
SingleVlanHeader{
priority_code_point: (bytes[0] >> 5) & 0b0000_0111u8,
drop_eligible_indicator: 0 != (bytes[0] & 0b0001_0000u8),
vlan_identifier: u16::from_be_bytes(
[
bytes[0] & 0b0000_1111u8,
bytes[1]
]
),
ether_type: u16::from_be_bytes(
[
bytes[2],
bytes[3],
]
),
}
}
pub fn read<T: io::Read + io::Seek + Sized >(reader: &mut T) -> Result<SingleVlanHeader, io::Error> {
let buffer = {
let mut buffer : [u8; SingleVlanHeader::SERIALIZED_SIZE] = [0;SingleVlanHeader::SERIALIZED_SIZE];
reader.read_exact(&mut buffer)?;
buffer
};
Ok(SingleVlanHeaderSlice{
slice: &buffer
}.to_header())
}
#[inline]
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), WriteError> {
writer.write_all(&self.to_bytes()?)?;
Ok(())
}
#[inline]
pub fn header_len(&self) -> usize {
4
}
#[inline]
pub fn to_bytes(&self) -> Result<[u8;4], ValueError> {
use crate::ErrorField::*;
max_check_u8(self.priority_code_point, 0x7, VlanTagPriorityCodePoint)?;
max_check_u16(self.vlan_identifier, 0xfff, VlanTagVlanId)?;
let id_be = self.vlan_identifier.to_be_bytes();
let eth_type_be = self.ether_type.to_be_bytes();
Ok(
[
(
if self.drop_eligible_indicator {
id_be[0] | 0x10
} else {
id_be[0]
} | (self.priority_code_point << 5)
),
id_be[1],
eth_type_be[0],
eth_type_be[1]
]
)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DoubleVlanHeader {
pub outer: SingleVlanHeader,
pub inner: SingleVlanHeader
}
impl SerializedSize for DoubleVlanHeader {
const SERIALIZED_SIZE: usize = 8;
}
impl DoubleVlanHeader {
#[deprecated(
since = "0.10.1",
note = "Use SingleVlanHeader::from_slice instead."
)]
#[inline]
pub fn read_from_slice(slice: &[u8]) -> Result<(DoubleVlanHeader, &[u8]), ReadError> {
DoubleVlanHeader::from_slice(slice)
}
#[inline]
pub fn from_slice(slice: &[u8]) -> Result<(DoubleVlanHeader, &[u8]), ReadError> {
Ok((
DoubleVlanHeaderSlice::from_slice(slice)?.to_header(),
&slice[DoubleVlanHeader::SERIALIZED_SIZE .. ]
))
}
pub fn read<T: io::Read + io::Seek + Sized >(reader: &mut T) -> Result<DoubleVlanHeader, ReadError> {
let outer = SingleVlanHeader::read(reader)?;
use crate::ether_type::{ VLAN_TAGGED_FRAME, PROVIDER_BRIDGING, VLAN_DOUBLE_TAGGED_FRAME };
match outer.ether_type {
VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
Ok(DoubleVlanHeader{
outer,
inner: SingleVlanHeader::read(reader)?
})
},
value => {
use crate::ReadError::*;
Err(DoubleVlanOuterNonVlanEtherType(value))
}
}
}
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), WriteError> {
self.outer.write(writer)?;
self.inner.write(writer)
}
#[inline]
pub fn header_len(&self) -> usize {
8
}
#[inline]
pub fn to_bytes(&self) -> Result<[u8;8], ValueError> {
let outer = self.outer.to_bytes()?;
let inner = self.inner.to_bytes()?;
Ok(
[
outer[0],
outer[1],
outer[2],
outer[3],
inner[0],
inner[1],
inner[2],
inner[3],
]
)
}
}
impl Default for DoubleVlanHeader {
fn default() -> Self {
DoubleVlanHeader {
outer: SingleVlanHeader {
priority_code_point: 0,
drop_eligible_indicator: false,
vlan_identifier: 0,
ether_type: ether_type::VLAN_TAGGED_FRAME,
},
inner: Default::default()
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SingleVlanHeaderSlice<'a> {
slice: &'a [u8]
}
impl<'a> SingleVlanHeaderSlice<'a> {
#[inline]
pub fn from_slice(slice: &'a[u8]) -> Result<SingleVlanHeaderSlice<'a>, ReadError>{
use crate::ReadError::*;
if slice.len() < SingleVlanHeader::SERIALIZED_SIZE {
return Err(UnexpectedEndOfSlice(SingleVlanHeader::SERIALIZED_SIZE));
}
Ok(SingleVlanHeaderSlice::<'a> {
slice: unsafe {
from_raw_parts(
slice.as_ptr(),
SingleVlanHeader::SERIALIZED_SIZE
)
}
})
}
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}
#[inline]
pub fn priority_code_point(&self) -> u8 {
unsafe {
*self.slice.get_unchecked(0) >> 5
}
}
#[inline]
pub fn drop_eligible_indicator(&self) -> bool {
unsafe {
0 != (*self.slice.get_unchecked(0) & 0x10)
}
}
#[inline]
pub fn vlan_identifier(&self) -> u16 {
u16::from_be_bytes(
unsafe {
[
*self.slice.get_unchecked(0) & 0xf,
*self.slice.get_unchecked(1)
]
}
)
}
#[inline]
pub fn ether_type(&self) -> u16 {
unsafe {
get_unchecked_be_u16(self.slice.as_ptr().add(2))
}
}
#[inline]
pub fn to_header(&self) -> SingleVlanHeader {
SingleVlanHeader {
priority_code_point: self.priority_code_point(),
drop_eligible_indicator: self.drop_eligible_indicator(),
vlan_identifier: self.vlan_identifier(),
ether_type: self.ether_type(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DoubleVlanHeaderSlice<'a> {
slice: &'a [u8]
}
impl<'a> DoubleVlanHeaderSlice<'a> {
pub fn from_slice(slice: &'a[u8]) -> Result<DoubleVlanHeaderSlice<'a>, ReadError>{
use crate::ReadError::*;
if slice.len() < DoubleVlanHeader::SERIALIZED_SIZE {
return Err(UnexpectedEndOfSlice(DoubleVlanHeader::SERIALIZED_SIZE));
}
let result = DoubleVlanHeaderSlice {
slice: unsafe {
from_raw_parts(
slice.as_ptr(),
DoubleVlanHeader::SERIALIZED_SIZE,
)
}
};
use ether_type::*;
match result.outer().ether_type() {
VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
Ok(result)
},
value => {
Err(DoubleVlanOuterNonVlanEtherType(value))
}
}
}
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}
#[inline]
pub fn outer(&self) -> SingleVlanHeaderSlice<'a> {
SingleVlanHeaderSlice::<'a> {
slice: unsafe {
from_raw_parts(
self.slice.as_ptr(),
SingleVlanHeader::SERIALIZED_SIZE
)
}
}
}
#[inline]
pub fn inner(&self) -> SingleVlanHeaderSlice<'a> {
SingleVlanHeaderSlice::<'a> {
slice: unsafe {
from_raw_parts(
self.slice.as_ptr().add(SingleVlanHeader::SERIALIZED_SIZE),
SingleVlanHeader::SERIALIZED_SIZE
)
}
}
}
pub fn to_header(&self) -> DoubleVlanHeader {
DoubleVlanHeader {
outer: self.outer().to_header(),
inner: self.inner().to_header()
}
}
}