use capnp::capability::Promise;
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, RpcSystem};
use futures::AsyncReadExt;
use crate::iterators::ConFrameIterator;
use crate::writer::ConFrameWriter;
use super::convert::{fill_frame_builder, frame_from_reader};
use super::read_con_capnp::read_con_service;
struct ReadConServiceImpl;
impl read_con_service::Server for ReadConServiceImpl {
fn parse_frames(
&mut self,
params: read_con_service::ParseFramesParams,
mut results: read_con_service::ParseFramesResults,
) -> Promise<(), capnp::Error> {
let req = pry!(params.get());
let file_bytes = pry!(pry!(req.get_req()).get_file_contents());
let file_str = match std::str::from_utf8(file_bytes) {
Ok(s) => s,
Err(e) => return Promise::err(capnp::Error::failed(e.to_string())),
};
let frames: Result<Vec<_>, _> = ConFrameIterator::new(file_str).collect();
let frames = match frames {
Ok(f) => f,
Err(e) => return Promise::err(capnp::Error::failed(e.to_string())),
};
let mut result_builder = results.get().init_result();
let mut frames_builder = result_builder.reborrow().init_frames(frames.len() as u32);
for (i, frame) in frames.iter().enumerate() {
let fb = frames_builder.reborrow().get(i as u32);
if let Err(e) = fill_frame_builder(fb, frame) {
return Promise::err(capnp::Error::failed(e));
}
}
Promise::ok(())
}
fn write_frames(
&mut self,
params: read_con_service::WriteFramesParams,
mut results: read_con_service::WriteFramesResults,
) -> Promise<(), capnp::Error> {
let req = pry!(params.get());
let frame_data_list = pry!(pry!(req.get_req()).get_frames());
let mut frames = Vec::with_capacity(frame_data_list.len() as usize);
for i in 0..frame_data_list.len() {
let fd = frame_data_list.get(i);
match frame_from_reader(fd) {
Ok(f) => frames.push(f),
Err(e) => return Promise::err(capnp::Error::failed(e)),
}
}
let mut buffer: Vec<u8> = Vec::new();
{
let mut writer = ConFrameWriter::new(&mut buffer);
if let Err(e) = writer.extend(frames.iter()) {
return Promise::err(capnp::Error::failed(e.to_string()));
}
}
results.get().init_result().set_file_contents(&buffer);
Promise::ok(())
}
}
pub async fn start_server(addr: &str) -> Result<(), Box<dyn std::error::Error>> {
let listener = tokio::net::TcpListener::bind(addr).await?;
let service: read_con_service::Client = capnp_rpc::new_client(ReadConServiceImpl);
loop {
let (stream, _) = listener.accept().await?;
stream.set_nodelay(true)?;
let (reader, writer) = tokio_util::compat::TokioAsyncReadCompatExt::compat(stream).split();
let network = twoparty::VatNetwork::new(
reader,
writer,
rpc_twoparty_capnp::Side::Server,
Default::default(),
);
let rpc_system = RpcSystem::new(Box::new(network), Some(service.clone().client));
tokio::task::spawn_local(rpc_system);
}
}