wick-packet 0.17.0

Packet, stream, and entity types for Wick, a WebAssembly application flow runtime
Documentation
use serde::de::DeserializeOwned;
use wasmrs_runtime::ConditionallySend;

use crate::{Error, Packet, PacketError, PacketExt, PacketPayload};

#[derive(Debug)]
pub struct VPacket<T>
where
  T: ConditionallySend,
{
  pub(crate) packet: Option<Result<Packet, anyhow::Error>>,
  pub(crate) value: Option<T>,
}

impl<T> VPacket<T>
where
  T: ConditionallySend,
{
  pub fn new(packet: Packet) -> Self
  where
    T: DeserializeOwned,
  {
    Self {
      value: Default::default(),
      packet: Some(Ok(packet)),
    }
  }

  pub fn from_result(packet: Result<Packet, anyhow::Error>) -> Self
  where
    T: DeserializeOwned + ConditionallySend,
  {
    Self {
      value: Default::default(),
      packet: Some(packet),
    }
  }

  pub const fn from_value(value: T) -> Self {
    VPacket {
      packet: None,
      value: Some(value),
    }
  }

  pub fn decode(self) -> Result<T, Error>
  where
    T: DeserializeOwned + ConditionallySend,
  {
    match self.value {
      Some(value) => Ok(value),
      None => match self.packet {
        Some(Ok(packet)) => packet.decode::<T>(),
        Some(Err(e)) => Err(Error::Component(e.to_string())),
        None => unreachable!("tried to decode VPacket that had no packet or value"),
      },
    }
  }
}

impl<T> From<Result<Packet, anyhow::Error>> for VPacket<T>
where
  T: DeserializeOwned + ConditionallySend,
{
  fn from(packet: Result<Packet, anyhow::Error>) -> Self {
    Self::from_result(packet)
  }
}

impl<T> From<VPacket<T>> for PacketPayload
where
  T: ConditionallySend + serde::Serialize,
{
  fn from(packet: VPacket<T>) -> Self {
    match packet.packet {
      Some(Ok(p)) => p.payload,
      Some(Err(e)) => PacketPayload::Err(PacketError::new(e.to_string())),
      None => packet.value.map_or_else(
        || unreachable!("tried to convert VPacket that had no packet or value"),
        |v| PacketPayload::encode(v),
      ),
    }
  }
}

impl<T> PacketExt for VPacket<T>
where
  T: ConditionallySend,
{
  fn has_data(&self) -> bool {
    match self.value {
      Some(_) => true,
      None => self
        .packet
        .as_ref()
        .map_or(false, |p| p.as_ref().map_or(false, |p| p.has_data())),
    }
  }

  fn port(&self) -> &str {
    self.packet.as_ref().map_or_else(
      || panic!("tried to query port for VPacket created manually"),
      |p| p.as_ref().map_or(Packet::FATAL_ERROR, |p| p.port()),
    )
  }

  fn flags(&self) -> u8 {
    match self.value {
      Some(_) => 0,
      None => self.packet.as_ref().map_or(0, |p| p.as_ref().map_or(0, |p| p.flags())),
    }
  }
}