wick_packet/
vpacket.rs

1use serde::de::DeserializeOwned;
2use wasmrs_runtime::ConditionallySend;
3
4use crate::{Error, Packet, PacketError, PacketExt, PacketPayload};
5
6#[derive(Debug)]
7pub struct VPacket<T>
8where
9  T: ConditionallySend,
10{
11  pub(crate) packet: Option<Result<Packet, anyhow::Error>>,
12  pub(crate) value: Option<T>,
13}
14
15impl<T> VPacket<T>
16where
17  T: ConditionallySend,
18{
19  pub fn new(packet: Packet) -> Self
20  where
21    T: DeserializeOwned,
22  {
23    Self {
24      value: Default::default(),
25      packet: Some(Ok(packet)),
26    }
27  }
28
29  pub fn from_result(packet: Result<Packet, anyhow::Error>) -> Self
30  where
31    T: DeserializeOwned + ConditionallySend,
32  {
33    Self {
34      value: Default::default(),
35      packet: Some(packet),
36    }
37  }
38
39  pub const fn from_value(value: T) -> Self {
40    VPacket {
41      packet: None,
42      value: Some(value),
43    }
44  }
45
46  pub fn decode(self) -> Result<T, Error>
47  where
48    T: DeserializeOwned + ConditionallySend,
49  {
50    match self.value {
51      Some(value) => Ok(value),
52      None => match self.packet {
53        Some(Ok(packet)) => packet.decode::<T>(),
54        Some(Err(e)) => Err(Error::Component(e.to_string())),
55        None => unreachable!("tried to decode VPacket that had no packet or value"),
56      },
57    }
58  }
59}
60
61impl<T> From<Result<Packet, anyhow::Error>> for VPacket<T>
62where
63  T: DeserializeOwned + ConditionallySend,
64{
65  fn from(packet: Result<Packet, anyhow::Error>) -> Self {
66    Self::from_result(packet)
67  }
68}
69
70impl<T> From<VPacket<T>> for PacketPayload
71where
72  T: ConditionallySend + serde::Serialize,
73{
74  fn from(packet: VPacket<T>) -> Self {
75    match packet.packet {
76      Some(Ok(p)) => p.payload,
77      Some(Err(e)) => PacketPayload::Err(PacketError::new(e.to_string())),
78      None => packet.value.map_or_else(
79        || unreachable!("tried to convert VPacket that had no packet or value"),
80        |v| PacketPayload::encode(v),
81      ),
82    }
83  }
84}
85
86impl<T> PacketExt for VPacket<T>
87where
88  T: ConditionallySend,
89{
90  fn has_data(&self) -> bool {
91    match self.value {
92      Some(_) => true,
93      None => self
94        .packet
95        .as_ref()
96        .map_or(false, |p| p.as_ref().map_or(false, |p| p.has_data())),
97    }
98  }
99
100  fn port(&self) -> &str {
101    self.packet.as_ref().map_or_else(
102      || panic!("tried to query port for VPacket created manually"),
103      |p| p.as_ref().map_or(Packet::FATAL_ERROR, |p| p.port()),
104    )
105  }
106
107  fn flags(&self) -> u8 {
108    match self.value {
109      Some(_) => 0,
110      None => self.packet.as_ref().map_or(0, |p| p.as_ref().map_or(0, |p| p.flags())),
111    }
112  }
113}