use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::PluginTransport;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum PluginInvocationWorkload {
RealtimeMedia,
Observer,
Offline,
}
#[derive(Debug, Error, Clone, Copy, PartialEq, Eq)]
#[error("plugin transport {transport:?} cannot serve {workload:?} workload")]
pub struct PluginInvocationPolicyError {
workload: PluginInvocationWorkload,
transport: PluginTransport,
}
impl PluginInvocationPolicyError {
pub const fn workload(self) -> PluginInvocationWorkload {
self.workload
}
pub const fn transport(self) -> PluginTransport {
self.transport
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct PluginInvocationPolicy;
impl PluginInvocationPolicy {
pub const fn standard() -> Self {
Self
}
pub fn validate(
self,
workload: PluginInvocationWorkload,
transport: PluginTransport,
) -> Result<(), PluginInvocationPolicyError> {
if transport == PluginTransport::Wasm && workload == PluginInvocationWorkload::RealtimeMedia
{
return Err(PluginInvocationPolicyError {
workload,
transport,
});
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn standard_policy_rejects_only_wasm_realtime_media() {
let policy = PluginInvocationPolicy::standard();
for workload in [
PluginInvocationWorkload::RealtimeMedia,
PluginInvocationWorkload::Observer,
PluginInvocationWorkload::Offline,
] {
assert_eq!(policy.validate(workload, PluginTransport::Native), Ok(()));
}
assert_eq!(
policy.validate(
PluginInvocationWorkload::RealtimeMedia,
PluginTransport::Wasm,
),
Err(PluginInvocationPolicyError {
workload: PluginInvocationWorkload::RealtimeMedia,
transport: PluginTransport::Wasm,
})
);
for workload in [
PluginInvocationWorkload::Observer,
PluginInvocationWorkload::Offline,
] {
assert_eq!(policy.validate(workload, PluginTransport::Wasm), Ok(()));
}
}
}