Files
simple-rust-tests/__ffi/abi_stable_crates/application/src/app.rs

207 lines
6.5 KiB
Rust

use super::*;
use std::time::{Duration,Instant};
pub struct TheApplication{
pub(super) plugins:Vec<PluginType>,
pub(super) state:ApplicationState,
}
pub struct ApplicationState{
// This is separate so that I can use the address
// of a PluginType to find its index inside of plugins.
pub(super) plugin_ids:Vec<PluginId>,
pub(super) id_map:HashMap<RString,PluginModAndIndices>,
pub(super) delayed_commands:VecDeque<DelayedCommand>,
pub(super) responses:VecDeque<DelayedResponse>,
pub(super) sender:RSender<AsyncCommand>,
pub(super) receiver:RReceiver<AsyncCommand>,
pub(super) last_run_at:Instant,
}
fn print_response(
plugin_id:&PluginId,
response:&str,
){
println!(
"reponse:\n{}\nfrom:\n {:?}\n\n",
response.left_pad(4),
plugin_id,
);
}
impl TheApplication{
/// Runs a command,
pub fn run_command(&mut self,which_plugin:WhichPlugin,command:RStr<'_>)->Result<(),AppError>{
let list=self.state.expand_which_plugin(which_plugin)?;
for index in list {
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
let plugin=&mut self.plugins[index as usize];
println!("command:\n{}", command.left_pad(4));
let resp=plugin.json_command(command,state).into_result()?;
self.state.register_command_run();
print_response(&self.state.plugin_ids[index],&resp);
}
Ok(())
}
pub fn tick(&mut self) -> Result<(), AppError>{
if let Ok(ac)=self.state.receiver.try_recv() {
self.state.send_command_to_plugin(&ac.from,ac.which_plugin,ac.command).into_result()?;
}
if let Some(dc)=self.state.delayed_commands.pop_front() {
self.run_command_(&dc.from,dc.plugin_index,&dc.command)?;
}
let mut responses=mem::replace(&mut self.state.responses, VecDeque::new());
for DelayedResponse{to,from,response} in responses.drain(..) {
let response=PluginResponse::owned_response(from,response);
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
if let RSome(res)=self.plugins[to]
.handle_response(response, state)
.into_result()?
{
print_response(&res.plugin_id, &res.response);
}
}
self.state.responses=responses;
Ok(())
}
pub fn is_finished(&self)->bool{
self.state.last_run_at.elapsed()>=Duration::from_secs(5)
}
fn run_command_(&mut self,from:&PluginId, to:usize, command:&str) -> Result<(), AppError> {
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
let response=self.plugins[to].json_command(command.into(),state).into_result()?;
let to=self.state.index_for_plugin_id(from)?;
self.state.register_command_run();
let response = DelayedResponse {
from:self.state.plugin_ids[to].clone(),
to,
response,
};
self.state.responses.push_back(response);
Ok(())
}
}
impl ApplicationState{
pub(crate) fn new() -> Self {
let (sender,receiver)=crossbeam_channel::unbounded();
Self{
plugin_ids:Vec::new(),
id_map:HashMap::new(),
delayed_commands:VecDeque::new(),
responses:VecDeque::new(),
sender,
receiver,
last_run_at:Instant::now(),
}
}
fn register_command_run(&mut self) {
self.last_run_at=Instant::now();
}
fn index_for_plugin_id(&self, id:&PluginId) -> Result<usize,AppError> {
self.id_map.get(&*id.named)
.and_then(|x| x.indices.get(id.instance as usize).cloned())
.ok_or_else(|| AppError::InvalidPlugin(WhichPlugin::Id(id.clone())))
}
fn expand_which_plugin(&self, which_plugin:WhichPlugin) -> Result<PluginIndices, AppError> {
match which_plugin {
WhichPlugin::Id(id)=>{
self.index_for_plugin_id(&id)
.map(|i| PluginIndices::from([i]) )
},
WhichPlugin::First{ref named}
| WhichPlugin::Last{ref named}
| WhichPlugin::Every{ref named} => {
self.id_map.get(&**named).and_then(|x| {
let list=&x.indices;
match which_plugin {
WhichPlugin::First{..} => {
PluginIndices::from([*list.first()?])
},
WhichPlugin::Last{..} => {
PluginIndices::from([*list.last()?])
},
WhichPlugin::Every{..} => {
PluginIndices::from(&**list)
},
_=>unreachable!(),
}.piped(Some)
})
.ok_or_else(|| AppError::InvalidPlugin(which_plugin.clone()))
},
WhichPlugin::Many(list) => {
let mut plugin_indices=PluginIndices::new();
for elem in list {
plugin_indices.extend(self.expand_which_plugin(elem)?);
}
Ok(plugin_indices)
}
}
}
}
impl Application for ApplicationState {
fn send_command_to_plugin(
&mut self,
from:&PluginId,
which_plugin:WhichPlugin,
command:RString,
) -> RResult<(),AppError> {
self.expand_which_plugin(which_plugin).map(|plugin_indices|{
let command=Arc::new(command);
for plugin_index in plugin_indices {
let from=from.clone();
self.delayed_commands.push_back(DelayedCommand {
from,
plugin_index,
command:command.clone(),
});
}
}).into()
}
fn get_plugin_id(&self, which_plugin:WhichPlugin) -> RResult<RVec<PluginId>, AppError> {
self.expand_which_plugin(which_plugin)
.map(|list|{
list.into_iter()
.map(|i| self.plugin_ids[i].clone() )
.collect::<RVec<PluginId>>()
})
.into()
}
fn sender(&self) -> RSender<AsyncCommand> {
self.sender.clone()
}
fn loaded_plugins(&self) -> RVec<PluginId> {
self.plugin_ids.clone().into()
}
}
////////////////////////////////////////////////////////////////////////////////