pub(crate) mod conversions;
use std::time::Duration;
use serde::{Deserialize, Serialize};
pub use wick_interface_types::*;
use wick_packet::{Metadata, Packet, PacketError, PacketPayload, WickMetadata};
use crate::rpc::{self, packet as rpc_packet, Packet as RpcPacket};
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
#[non_exhaustive]
pub struct Statistics {
pub name: String,
pub runs: u32,
pub errors: u32,
pub execution_duration: Option<DurationStatistics>,
}
mod as_micros {
use std::convert::TryInto;
use std::time::Duration;
use serde::{Deserialize, Deserializer, Serializer};
pub(crate) fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u64(duration.as_micros().try_into().unwrap_or(u64::MAX))
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
let micros = u64::deserialize(deserializer)?;
Ok(Duration::from_micros(micros))
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[non_exhaustive]
pub struct DurationStatistics {
#[serde(with = "as_micros")]
pub max_time: Duration,
#[serde(with = "as_micros")]
pub min_time: Duration,
#[serde(with = "as_micros")]
pub average_time: Duration,
#[serde(with = "as_micros")]
pub total_time: Duration,
}
impl DurationStatistics {
#[must_use]
pub const fn new(min_time: Duration, max_time: Duration, average_time: Duration, total_time: Duration) -> Self {
Self {
max_time,
min_time,
average_time,
total_time,
}
}
}
impl RpcPacket {
pub fn into_packet(self) -> Packet {
self.into()
}
}
impl From<RpcPacket> for Packet {
fn from(v: RpcPacket) -> Self {
let (op, port, done) = v.metadata.map_or_else(
|| (0, Packet::FATAL_ERROR.to_owned(), 0_u8),
|m| (m.index, m.port, m.flags.try_into().unwrap()),
);
Self::new_raw(
v.data
.map_or(PacketPayload::fatal_error("Could not decode RPC message"), |p| p.into()),
Metadata::new(op),
WickMetadata::new(port, done),
)
}
}
impl From<rpc_packet::Data> for PacketPayload {
fn from(v: rpc_packet::Data) -> Self {
match v {
rpc_packet::Data::Ok(v) => PacketPayload::Ok(match v.data {
Some(rpc::ok::Data::Messagepack(v)) => Some(v.into()),
Some(rpc::ok::Data::Json(_v)) => todo!(),
None => unreachable!(),
}),
rpc_packet::Data::Err(v) => PacketPayload::Err(PacketError::new(v.message)),
}
}
}
impl From<PacketPayload> for rpc_packet::Data {
fn from(v: PacketPayload) -> Self {
match v {
PacketPayload::Ok(v) => rpc_packet::Data::Ok(rpc::Ok {
data: Some(rpc::ok::Data::Messagepack(v.map_or_else(Vec::new, |v| v.to_vec()))),
}),
PacketPayload::Err(e) => rpc_packet::Data::Err(rpc::Err {
message: e.msg().to_owned(),
code: 513,
}),
}
}
}