#![cfg_attr(coverage_nightly, coverage(off))]
use crate::transport::{PmcpTransportWrapper, TransportAdapter, TransportError};
use pmcp::transport::StdioTransport;
use std::fmt::Debug;
use tracing::debug;
#[derive(Debug)]
pub struct StdioTransportAdapter {
wrapper: PmcpTransportWrapper<StdioTransport>,
}
impl StdioTransportAdapter {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn new() -> Result<Self, TransportError> {
debug!("Initializing stdio transport");
let inner = StdioTransport::new();
let wrapper = PmcpTransportWrapper::new(inner);
Ok(Self { wrapper })
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn boxed() -> Result<Box<dyn TransportAdapter>, TransportError> {
Ok(Box::new(Self::new().await?))
}
}
#[async_trait::async_trait]
impl TransportAdapter for StdioTransportAdapter {
async fn send(&mut self, message: pmcp::transport::TransportMessage) -> Result<(), TransportError> {
self.wrapper.send(message).await
}
async fn receive(&mut self) -> Result<pmcp::transport::TransportMessage, TransportError> {
self.wrapper.receive().await
}
async fn close(&mut self) -> Result<(), TransportError> {
self.wrapper.close().await
}
fn is_connected(&self) -> bool {
self.wrapper.is_connected()
}
fn transport_type(&self) -> &'static str {
"stdio"
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn test_frame_boundary_preservation(messages in prop::collection::vec("\\PC+", 1..10)) {
prop_assert!(!messages.is_empty());
}
}
#[tokio::test]
async fn test_stdio_transport_creation() {
if std::io::stdin().is_terminal() {
let transport = StdioTransportAdapter::new().await;
assert!(transport.is_ok());
if let Ok(t) = transport {
assert_eq!(t.transport_type(), "stdio");
}
}
}
#[test]
fn test_stdio_transport_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<StdioTransportAdapter>();
}
}