use std::fmt::Display;
use crate::{
core::{macros::impl_from, view::View},
dataplane_path::{
model::DpPath,
onehop::view::OneHopPathView,
standard::view::StandardPathView,
types::{PathReverseError, PathType},
},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScionDpPathViewRef<'a> {
Standard(&'a StandardPathView),
OneHop(&'a OneHopPathView),
Unsupported {
path_type: PathType,
data: &'a [u8],
},
Empty,
}
impl ScionDpPathViewExt for ScionDpPathViewRef<'_> {
#[inline]
fn as_ref(&self) -> ScionDpPathViewRef<'_> {
*self
}
}
impl<'a> From<&'a StandardPathView> for ScionDpPathViewRef<'a> {
#[inline]
fn from(value: &'a StandardPathView) -> Self {
ScionDpPathViewRef::Standard(value)
}
}
impl<'a> From<&'a OneHopPathView> for ScionDpPathViewRef<'a> {
#[inline]
fn from(value: &'a OneHopPathView) -> Self {
ScionDpPathViewRef::OneHop(value)
}
}
impl Display for ScionDpPathViewRef<'_> {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.display(f)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum ScionDpPathViewRefMut<'a> {
Standard(&'a mut StandardPathView),
OneHop(&'a mut OneHopPathView),
Unsupported {
path_type: PathType,
buf: &'a mut [u8],
},
Empty,
}
impl ScionDpPathViewExt for ScionDpPathViewRefMut<'_> {
#[inline]
fn as_ref(&self) -> ScionDpPathViewRef<'_> {
match self {
ScionDpPathViewRefMut::Standard(standard_path_view) => {
ScionDpPathViewRef::Standard(standard_path_view)
}
ScionDpPathViewRefMut::OneHop(one_hop_path_view) => {
ScionDpPathViewRef::OneHop(one_hop_path_view)
}
ScionDpPathViewRefMut::Unsupported { path_type, buf } => {
ScionDpPathViewRef::Unsupported {
path_type: *path_type,
data: buf,
}
}
ScionDpPathViewRefMut::Empty => ScionDpPathViewRef::Empty,
}
}
}
impl ScionDpPathViewExtMut for ScionDpPathViewRefMut<'_> {
#[inline]
fn as_mut(&mut self) -> ScionDpPathViewRefMut<'_> {
match self {
ScionDpPathViewRefMut::Standard(v) => ScionDpPathViewRefMut::Standard(v),
ScionDpPathViewRefMut::OneHop(v) => ScionDpPathViewRefMut::OneHop(v),
ScionDpPathViewRefMut::Unsupported { path_type, buf } => {
ScionDpPathViewRefMut::Unsupported {
path_type: *path_type,
buf,
}
}
ScionDpPathViewRefMut::Empty => ScionDpPathViewRefMut::Empty,
}
}
}
impl<'a> From<&'a mut StandardPathView> for ScionDpPathViewRef<'a> {
#[inline]
fn from(value: &'a mut StandardPathView) -> Self {
ScionDpPathViewRef::Standard(value)
}
}
impl<'a> From<&'a mut OneHopPathView> for ScionDpPathViewRef<'a> {
#[inline]
fn from(value: &'a mut OneHopPathView) -> Self {
ScionDpPathViewRef::OneHop(value)
}
}
impl Display for ScionDpPathViewRefMut<'_> {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.display(f)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ScionDpPathView {
Standard(Box<StandardPathView>),
OneHop(OneHopPathView),
Unsupported {
path_type: PathType,
data: Box<[u8]>,
},
Empty,
}
impl ScionDpPathViewExt for ScionDpPathView {
#[inline]
fn as_ref(&self) -> ScionDpPathViewRef<'_> {
match self {
ScionDpPathView::Standard(standard_path_view) => {
ScionDpPathViewRef::Standard(standard_path_view.as_ref())
}
ScionDpPathView::OneHop(one_hop_path_view) => {
ScionDpPathViewRef::OneHop(one_hop_path_view)
}
ScionDpPathView::Unsupported { path_type, data } => {
ScionDpPathViewRef::Unsupported {
path_type: *path_type,
data: data.as_ref(),
}
}
ScionDpPathView::Empty => ScionDpPathViewRef::Empty,
}
}
}
impl ScionDpPathViewExtMut for ScionDpPathView {
#[inline]
fn as_mut(&mut self) -> ScionDpPathViewRefMut<'_> {
match self {
ScionDpPathView::Standard(standard_path_view) => {
ScionDpPathViewRefMut::Standard(standard_path_view.as_mut())
}
ScionDpPathView::OneHop(one_hop_path_view) => {
ScionDpPathViewRefMut::OneHop(one_hop_path_view)
}
ScionDpPathView::Unsupported { path_type, data } => {
ScionDpPathViewRefMut::Unsupported {
path_type: *path_type,
buf: data.as_mut(),
}
}
ScionDpPathView::Empty => ScionDpPathViewRefMut::Empty,
}
}
}
impl_from!(Box<StandardPathView>, ScionDpPathView, |v| {
ScionDpPathView::Standard(v)
});
impl_from!(OneHopPathView, ScionDpPathView, |v| {
ScionDpPathView::OneHop(v)
});
impl Display for ScionDpPathView {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.display(f)
}
}
pub trait ScionDpPathViewExt {
fn as_ref(&self) -> ScionDpPathViewRef<'_>;
#[inline]
fn to_owned_view(&self) -> ScionDpPathView {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
ScionDpPathView::Standard(standard_path_view.to_boxed())
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => {
ScionDpPathView::OneHop(one_hop_path_view.clone())
}
ScionDpPathViewRef::Unsupported { path_type, data } => {
ScionDpPathView::Unsupported {
path_type,
data: Box::from(data),
}
}
ScionDpPathViewRef::Empty => ScionDpPathView::Empty,
}
}
#[inline]
fn as_slice(&self) -> &[u8] {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => standard_path_view.as_slice(),
ScionDpPathViewRef::OneHop(one_hop_path_view) => one_hop_path_view.as_slice(),
ScionDpPathViewRef::Unsupported { data, .. } => data,
ScionDpPathViewRef::Empty => &[],
}
}
#[inline]
fn expiration(&self) -> Option<u32> {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
Some(standard_path_view.expiration())
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => Some(one_hop_path_view.expiration()),
ScionDpPathViewRef::Empty => Some(u32::MAX),
ScionDpPathViewRef::Unsupported { .. } => None,
}
}
#[inline]
fn first_egress_interface(&self) -> Option<u16> {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
let info_field = standard_path_view.info_fields().first()?;
let hop_field = standard_path_view.hop_fields().first()?;
Some(hop_field.egress_interface(info_field))
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => {
let info_field = one_hop_path_view.info_field();
let [hop_field, _] = one_hop_path_view.hop_fields();
Some(hop_field.egress_interface(info_field))
}
ScionDpPathViewRef::Empty => None,
ScionDpPathViewRef::Unsupported { .. } => None,
}
}
#[inline]
fn current_egress_interface(&self) -> Option<u16> {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
let info_field = standard_path_view.curr_info_field()?;
Some(
standard_path_view
.curr_hop_field()?
.egress_interface(info_field),
)
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => {
let info_field = one_hop_path_view.info_field();
let [hop_field, _] = one_hop_path_view.hop_fields();
Some(hop_field.egress_interface(info_field))
}
ScionDpPathViewRef::Empty => None,
ScionDpPathViewRef::Unsupported { .. } => None,
}
}
#[inline]
fn last_ingress_interface(&self) -> Option<u16> {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
let info_field = standard_path_view.info_fields().last()?;
Some(
standard_path_view
.hop_fields()
.last()?
.ingress_interface(info_field),
)
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => {
Some(
one_hop_path_view
.hop_fields()
.last()?
.ingress_interface(one_hop_path_view.info_field()),
)
}
ScionDpPathViewRef::Empty => None,
ScionDpPathViewRef::Unsupported { .. } => None,
}
}
#[inline]
fn current_ingress_interface(&self) -> Option<u16> {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => {
let info_field = standard_path_view.curr_info_field()?;
Some(
standard_path_view
.curr_hop_field()?
.ingress_interface(info_field),
)
}
ScionDpPathViewRef::OneHop(one_hop_path_view) => {
let info_field = one_hop_path_view.info_field();
let [_, hop_field] = one_hop_path_view.hop_fields();
Some(hop_field.ingress_interface(info_field))
}
ScionDpPathViewRef::Empty => None,
ScionDpPathViewRef::Unsupported { .. } => None,
}
}
#[inline]
fn to_model(&self) -> DpPath {
DpPath::from_view(&self.as_ref())
}
#[inline]
fn display(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.as_ref() {
ScionDpPathViewRef::Standard(standard_path_view) => write!(f, "{}", standard_path_view),
ScionDpPathViewRef::OneHop(one_hop_path_view) => write!(f, "{}", one_hop_path_view),
ScionDpPathViewRef::Unsupported { path_type, .. } => {
write!(f, "[unsupported] {:?}", path_type)
}
ScionDpPathViewRef::Empty => write!(f, "[empty]"),
}
}
}
impl<T: ScionDpPathViewExt> ScionDpPathViewExt for &T {
#[inline]
fn as_ref(&self) -> ScionDpPathViewRef<'_> {
(*self).as_ref()
}
}
pub trait ScionDpPathViewExtMut: ScionDpPathViewExt {
fn as_mut(&mut self) -> ScionDpPathViewRefMut<'_>;
#[inline]
fn try_reverse(&mut self) -> Result<&mut Self, PathReverseError>
where
Self: Sized,
{
let mut_self = self.as_mut();
match mut_self {
ScionDpPathViewRefMut::Standard(standard_path_view) => {
standard_path_view.try_reverse()?;
Ok(self)
}
ScionDpPathViewRefMut::OneHop(one_hop_path_view) => {
one_hop_path_view.try_reverse()?;
Ok(self)
}
ScionDpPathViewRefMut::Empty => Ok(self),
ScionDpPathViewRefMut::Unsupported { .. } => {
Err(PathReverseError::new(
"Cannot reverse unsupported path type",
))
}
}
}
#[inline]
fn try_into_reversed(mut self) -> Result<Self, (Self, PathReverseError)>
where
Self: Sized,
{
match self.try_reverse() {
Ok(_) => Ok(self),
Err(e) => Err((self, e)),
}
}
}