Skip to main content

viam_bridge_sdk/
bridge.rs

1use async_trait::async_trait;
2use tokio::runtime::Runtime;
3use std::{any::{Any, TypeId}, sync::Arc};
4use serde_json::Value;
5use anyhow::Result;
6use std::collections::HashMap;
7
8#[derive(Clone, Debug, Default)]
9pub struct Context {
10    pub component_id: Option<String>,
11    pub tracing: HashMap<String, String>,
12    // You could add more fields as needed:
13    // pub request_id: Option<String>,
14    // pub timestamp: Option<u64>,
15}
16
17pub struct BridgeContext {
18    runtime: Arc<Runtime>,
19    // Add other context fields as needed
20}
21
22impl BridgeContext {
23    pub fn new(runtime: Arc<Runtime>) -> Self {
24        Self { runtime }
25    }
26    
27    pub fn runtime(&self) -> Arc<Runtime> {
28        self.runtime.clone()
29    }
30}
31
32/// Interface for bridge instances that can be used at runtime
33#[async_trait]
34pub trait BridgeInstance: Send + Sync {  
35    /// Get instance as Any for downcasting
36    fn as_any(&self) -> &dyn Any;
37
38    fn is_async(&self) -> bool {
39        false // Default to sync
40    }
41    
42    /// Get all interfaces exposed by this bridge instance
43    fn get_interfaces(&self) -> Vec<BridgeInterface>;
44    
45    /// Dispatch a function call to this bridge instance
46    fn dispatch_call(
47        &self,
48        context: &Context,
49        interface_name: &str,
50        function_name: &str,
51        args: &[wasmtime::component::Val],
52        //store: &mut wasmtime::StoreContextMut<'_, ComApiWasmHost>,
53    ) -> Result<Vec<wasmtime::component::Val>, Box<dyn std::error::Error>>;
54
55    async fn dispatch_call_async(
56        &self,
57        context: &Context,
58        interface_name: &str,
59        function_name: &str,
60        args: &[wasmtime::component::Val],
61        //store: &mut wasmtime::StoreContextMut<'_, ComApiWasmHost>,
62        //host_state: &mut ComApiWasmHost,
63    ) -> Result<Vec<wasmtime::component::Val>, Box<dyn std::error::Error + Send + Sync>>;
64
65    //fn register_with_host(&self, linker: &mut wasmtime::component::Linker<ComApiWasmHost>, host: &mut ComApiWasmHost) ->  Result<()>; //anyhow::Result<Vec<(String, Box<dyn Fn<(wasmtime::StoreContextMut<'_, ComApiWasmHost>,), Output=anyhow::Result<(String,)>> + Send + 'static>)>>;
66}
67
68/// Represents a function parameter or result
69pub struct BridgeType {
70    /// The type of the parameter or result
71    pub ty: wasmtime::component::Type,
72    /// Optional name of the parameter (for documentation)
73    pub name: Option<String>,
74}
75
76/// Represents a function exposed by a bridge
77pub struct BridgeFunc {
78    /// Name of the function
79    pub name: String,
80    /// Parameters of the function
81    pub params: Vec<BridgeType>,
82    /// Results of the function
83    pub results: Vec<BridgeType>,
84    /// Optional documentation
85    pub docs: Option<String>,
86}
87
88/// Represents an interface exposed by a bridge
89pub struct BridgeInterface {
90    /// Full name of the interface (e.g., "postgres-bridge:db/db@0.1.0")
91    pub full_name: String,
92    /// Base namespace of the interface (e.g., "postgres-bridge:db")
93    pub namespace: String,
94    /// Functions exposed by this interface
95    pub functions: Vec<BridgeFunc>,
96}
97
98/// Core trait for extension bridges - these methods are all dyn-compatible
99pub trait ExtensionBridge: Send + Sync {
100    /// Get the bridge's name
101    fn name(&self) -> &str;
102    
103    /// Get the list of interfaces that this bridge provides
104    fn interfaces(&self) -> Vec<&str>;
105    
106    /// Initialize the bridge with configuration
107    fn initialize(&mut self, config: Value) -> Result<()>;
108    
109    /// Create bridge instances
110    fn create_instances(&self) -> Result<Vec<Arc<dyn BridgeInstance>>>;
111    
112    /// Get the bridge as Any for downcasting
113    fn as_any(&self) -> &dyn Any;
114    
115    /// Get the bridge as mutable Any for downcasting
116    fn as_any_mut(&mut self) -> &mut dyn Any;
117    
118    /// Get an object ID to uniquely identify this bridge
119    fn object_id(&self) -> TypeId;
120}
121
122/// Type-erased registry callback
123pub struct TypedRegistryCallback {
124    /// The type ID of the host type this callback works with
125    pub host_type_id: TypeId,
126    
127    /// The callback function, erased to an Any type
128    callback: Box<dyn Any + Send + Sync>,
129}
130
131impl TypedRegistryCallback {
132    // Create a new typed registry callback for a specific host type
133    // pub fn new<T: Send + 'static>(
134    //     callback: Box<dyn Fn(&mut Linker<T>, Box<dyn Fn(&T) -> &HostData + Send + Sync>) -> Result<()> + Send + Sync>
135    // ) -> Self {
136    //     Self {
137    //         host_type_id: TypeId::of::<T>(),
138    //         callback: Box::new(callback) as Box<dyn Any + Send + Sync>,
139    //     }
140    // }
141    
142    // /// Try to use this callback with a specific host type
143    // pub fn call<T: Send + 'static>(
144    //     &self,
145    //     linker: &mut Linker<T>,
146    //     host_accessor: Box<dyn Fn(&T) -> &HostData + Send + Sync>
147    // ) -> Result<()> {
148    //     if self.host_type_id != TypeId::of::<T>() {
149    //         return Err(anyhow::anyhow!("Type mismatch in registry callback"));
150    //     }
151        
152    //     let callback = self.callback
153    //         .downcast_ref::<Box<dyn Fn(&mut Linker<T>, Box<dyn Fn(&T) -> &HostData + Send + Sync>) -> Result<()> + Send + Sync>>()
154    //         .ok_or_else(|| anyhow::anyhow!("Failed to downcast registry callback"))?;
155            
156    //     callback(linker, host_accessor)
157    // }
158}
159
160/// Bridge type registry trait - handles registration for specific host types
161/// This is intentionally separate from ExtensionBridge to maintain dyn-compatibility
162pub trait BridgeTypeRegistry: Send + Sync {
163    /// Register a callback for a specific host type
164    fn register_callback(&mut self, callback: TypedRegistryCallback);
165    
166    /// Get callbacks that match a specific host type ID
167    fn get_callbacks_for(&self, host_type_id: TypeId) -> Vec<&TypedRegistryCallback>;
168}
169
170/// Combined trait for extension bridges that also support type registry
171pub trait ExtensionBridgeWithRegistry: ExtensionBridge + BridgeTypeRegistry {}
172
173// Auto-implement the combined trait for any type that implements both traits
174impl<T> ExtensionBridgeWithRegistry for T 
175where 
176    T: ExtensionBridge + BridgeTypeRegistry
177{}