1use std::collections::HashMap ;
10use std::sync::{ Mutex, MutexGuard, PoisonError };
11use wasmtime::component::Val ;
12
13use crate::plugin::PluginData ;
14use crate::interface::InterfaceData ;
15use crate::plugin_instance::PluginInstance ;
16use crate::DispatchError ;
17
18
19
20#[derive( Debug )]
36pub enum Socket<T, Id> {
37 AtMostOne( Option<T> ),
39 ExactlyOne( T ),
41 AtLeastOne( HashMap<Id, T> ),
43 Any( HashMap<Id, T> ),
45}
46
47impl<T, Id: Clone + std::hash::Hash + Eq> Socket<T, Id> {
48
49 pub(crate) fn map<N>( &self, mut map: impl FnMut( &T ) -> N ) -> Socket<N, Id> {
50 match self {
51 Self::AtMostOne( Option::None ) => Socket::AtMostOne( Option::None ),
52 Self::AtMostOne( Some( t ) ) => Socket::AtMostOne( Some( map( t ))),
53 Self::ExactlyOne( t ) => Socket::ExactlyOne( map( t )),
54 Self::AtLeastOne( vec ) => Socket::AtLeastOne( vec.iter().map(|( id, item ): ( &Id, _ )| ( id.clone(), map( item ) )).collect() ),
55 Self::Any( vec ) => Socket::Any( vec.iter().map(|( id, item ): ( &Id, _ )| ( id.clone(), map( item ) )).collect() ),
56 }
57 }
58
59 pub(crate) fn map_mut<N>( self, mut map: impl FnMut(T) -> N ) -> Socket<N, Id> {
60 match self {
61 Self::AtMostOne( Option::None ) => Socket::AtMostOne( Option::None ),
62 Self::AtMostOne( Some( t )) => Socket::AtMostOne( Some( map( t ))),
63 Self::ExactlyOne( t ) => Socket::ExactlyOne( map( t )),
64 Self::AtLeastOne( vec ) => Socket::AtLeastOne( vec.into_iter().map(|( id, item )| ( id, map( item ) )).collect() ),
65 Self::Any( vec ) => Socket::Any( vec.into_iter().map(|( id, item )| ( id, map( item ))).collect() ),
66 }
67 }
68}
69
70impl<P: PluginData> Socket<Mutex<PluginInstance<P>>, P::Id> {
71
72 #[allow( clippy::type_complexity )]
73 pub(crate) fn get( &self, id: &P::Id ) -> Result<Option<&Mutex<PluginInstance<P>>>,PoisonError<MutexGuard<'_, PluginInstance<P>>>> {
74 Ok( match self {
75 Self::AtMostOne( Option::None ) => None,
76 Self::AtMostOne( Some( plugin )) | Self::ExactlyOne( plugin ) => {
77 if &plugin.lock()?.id == id { Some( plugin ) } else { None }
78 },
79 Self::AtLeastOne( plugins ) | Self::Any( plugins ) => plugins.get( id ),
80 })
81 }
82
83 pub(crate) fn dispatch_function<I: InterfaceData>(
84 &self,
85 interface_path: &str,
86 function: &str,
87 has_return: bool,
88 data: &[Val],
89 ) -> Socket<Result<Val, DispatchError<I>>, P::Id> {
90 self.map(| plugin | plugin
91 .lock().map_err(|_| DispatchError::Deadlock )
92 .and_then(| mut lock | lock.dispatch( interface_path, function, has_return, data ))
93 )
94 }
95}
96
97impl<Id> From<Socket<Val, Id>> for Val {
98 fn from( socket: Socket<Val, Id> ) -> Self {
99 match socket {
100 Socket::AtMostOne( Option::None ) => Val::Option( Option::None ),
101 Socket::AtMostOne( Some( val )) => Val::Option( Some( Box::new( val ))),
102 Socket::ExactlyOne( val ) => val,
103 Socket::AtLeastOne( items )
104 | Socket::Any( items ) => Val::List( items.into_values().collect() ),
105 }
106 }
107}