rig_core/driver/
dyn_model.rs1use std::fmt;
6use std::sync::Arc;
7
8use super::{Model, Transport};
9use crate::error::ProviderError;
10use crate::observe::AdapterContext;
11use crate::streaming::Streamed;
12use crate::wasm_compat::{WasmCompatSend, WasmCompatSync};
13use crate::wire::{Capabilities, Descriptor, Mode, Operation, Wire};
14
15pub(crate) trait ErasedModel<Op: Operation>: WasmCompatSend + WasmCompatSync {
19 fn describe(&self) -> Descriptor<'_>;
20
21 fn open(
22 &self,
23 request: Op::Request,
24 mode: Mode,
25 observation: Option<AdapterContext>,
26 ) -> Result<Streamed<Op>, ProviderError>;
27}
28
29impl<W, T> ErasedModel<W::Op> for Model<W, T>
30where
31 W: Wire,
32 T: Transport<W>,
33{
34 fn describe(&self) -> Descriptor<'_> {
35 self.wire.describe()
36 }
37
38 fn open(
39 &self,
40 request: <W::Op as Operation>::Request,
41 mode: Mode,
42 observation: Option<AdapterContext>,
43 ) -> Result<Streamed<W::Op>, ProviderError> {
44 Model::open(self, request, mode, observation)
45 }
46}
47
48pub struct DynModel<Op: Operation> {
77 inner: Arc<dyn ErasedModel<Op>>,
78}
79
80impl<W, T> Model<W, T>
81where
82 W: Wire,
83 T: Transport<W>,
84{
85 pub fn erase(self) -> DynModel<W::Op> {
87 DynModel {
88 inner: Arc::new(self),
89 }
90 }
91}
92
93impl<W, T> From<Model<W, T>> for DynModel<W::Op>
94where
95 W: Wire,
96 T: Transport<W>,
97{
98 fn from(model: Model<W, T>) -> Self {
99 model.erase()
100 }
101}
102
103impl<Op: Operation> Clone for DynModel<Op> {
104 fn clone(&self) -> Self {
105 Self {
106 inner: Arc::clone(&self.inner),
107 }
108 }
109}
110
111impl<Op: Operation> fmt::Debug for DynModel<Op> {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 f.debug_struct("DynModel")
114 .field("name", &self.name())
115 .field("id", &self.id())
116 .finish()
117 }
118}
119
120impl<Op: Operation> DynModel<Op> {
121 pub fn name(&self) -> &str {
123 self.inner.describe().name
124 }
125
126 pub fn id(&self) -> Option<&str> {
128 self.inner.describe().model
129 }
130
131 pub fn capabilities(&self) -> Capabilities {
133 self.inner.describe().capabilities
134 }
135
136 pub fn call(
140 &self,
141 request: impl Into<Op::Request>,
142 ) -> impl Future<Output = Result<Op::Response, ProviderError>> + WasmCompatSend + 'static {
143 self.finished(request.into(), None)
144 }
145
146 pub fn call_observed(
148 &self,
149 request: impl Into<Op::Request>,
150 observation: AdapterContext,
151 ) -> impl Future<Output = Result<Op::Response, ProviderError>> + WasmCompatSend + 'static {
152 self.finished(request.into(), Some(observation))
153 }
154
155 fn finished(
157 &self,
158 request: Op::Request,
159 observation: Option<AdapterContext>,
160 ) -> impl Future<Output = Result<Op::Response, ProviderError>> + WasmCompatSend + 'static {
161 let inner = self.inner.clone();
162 async move {
163 inner
164 .open(request, Mode::Unary, observation)?
165 .finish()
166 .await
167 }
168 }
169
170 pub fn stream(&self, request: impl Into<Op::Request>) -> Result<Streamed<Op>, ProviderError> {
172 self.inner.open(request.into(), Mode::Streaming, None)
173 }
174
175 pub fn stream_observed(
177 &self,
178 request: impl Into<Op::Request>,
179 observation: AdapterContext,
180 ) -> Result<Streamed<Op>, ProviderError> {
181 self.inner
182 .open(request.into(), Mode::Streaming, Some(observation))
183 }
184}
185
186#[cfg(test)]
187mod tests;