use std::future::Future;
use std::pin::Pin;
use anyclaw_sdk_types::DeliverMedia;
use crate::error::ToolSdkError;
pub trait MediaDelivery: Send + Sync + 'static {
fn deliver(&self, media: DeliverMedia)
-> impl Future<Output = Result<(), ToolSdkError>> + Send;
}
pub trait DynMediaDelivery: Send + Sync + 'static {
fn deliver<'a>(
&'a self,
media: DeliverMedia,
) -> Pin<Box<dyn Future<Output = Result<(), ToolSdkError>> + Send + 'a>>;
}
impl<T: MediaDelivery> DynMediaDelivery for T {
fn deliver<'a>(
&'a self,
media: DeliverMedia,
) -> Pin<Box<dyn Future<Output = Result<(), ToolSdkError>> + Send + 'a>> {
Box::pin(MediaDelivery::deliver(self, media))
}
}
#[derive(Debug, Clone, Copy)]
pub struct NoopMediaDelivery;
impl MediaDelivery for NoopMediaDelivery {
async fn deliver(&self, _media: DeliverMedia) -> Result<(), ToolSdkError> {
Err(ToolSdkError::ExecutionFailed(
"media delivery not available: channel.deliver scope not granted".into(),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use anyclaw_sdk_types::MediaCategory;
use rstest::rstest;
#[rstest]
fn when_dyn_media_delivery_used_as_trait_object_then_compiles() {
fn _accepts_dyn(_d: &dyn DynMediaDelivery) {}
}
#[rstest]
#[tokio::test]
async fn when_noop_delivery_called_then_returns_scope_error() {
let noop = NoopMediaDelivery;
let media = DeliverMedia {
session_id: "test-session".into(),
data: vec![0x89, 0x50, 0x4E, 0x47],
mime_type: "image/png".into(),
filename: Some("test.png".into()),
category: MediaCategory::Image,
};
let result = MediaDelivery::deliver(&noop, media).await;
assert!(result.is_err());
let err = result.unwrap_err();
assert!(
err.to_string()
.contains("channel.deliver scope not granted")
);
}
#[rstest]
#[tokio::test]
async fn when_noop_delivery_used_as_dyn_then_returns_same_error() {
let noop: Box<dyn DynMediaDelivery> = Box::new(NoopMediaDelivery);
let media = DeliverMedia {
session_id: "s1".into(),
data: vec![1, 2, 3],
mime_type: "application/octet-stream".into(),
filename: None,
category: MediaCategory::File,
};
let result = noop.deliver(media).await;
assert!(result.is_err());
}
}