1use std::{fmt, rc::Rc};
3use futures::future::LocalBoxFuture;
4use lenso_kernel::{InvocationContext, NativeRequestEndpoint, NativeRequestFuture, NativeRequestHandle, PluginDependencies, RequestCapability, RuntimeFailure};
5
6use lenso_plugin_authoring::{BoundCapabilityClient, CapabilityClient, CapabilityClientMany};
7pub const CAPABILITY_ID: &str = "lenso.http.endpoint@1";
8pub const DESCRIPTOR_VERSION: &str = "1.1.0";
9pub const PORTABLE: bool = true;
10pub const CROSS_LANE_TRANSFER: bool = true;
11pub const ENDPOINT_CAPABILITY_ID: &str = CAPABILITY_ID;
12pub const ENDPOINT_DESCRIPTOR_VERSION: &str = DESCRIPTOR_VERSION;
13
14#[doc(hidden)]
15#[macro_export]
16macro_rules! __lenso_provided_endpoint { () => { "{\"capability_id\":\"lenso.http.endpoint@1\",\"descriptor_version\":\"1.1.0\",\"operations\":[\"describe\",\"handle\"],\"operation_kinds\":{},\"default_admission\":{\"queue_capacity\":0,\"max_concurrency\":1},\"operation_admissions\":{},\"event_admission\":null,\"cross_lane_transfer\":true}" }; }
17
18#[doc(hidden)]
19#[macro_export]
20macro_rules! __lenso_required_endpoint_client { () => { "{\"capability_id\":\"lenso.http.endpoint@1\",\"descriptor_version\":\"1.1.0\",\"cardinality\":\"one\"}" }; }
21
22#[doc(hidden)]
23#[macro_export]
24macro_rules! __lenso_required_many_endpoint_client { () => { "{\"capability_id\":\"lenso.http.endpoint@1\",\"descriptor_version\":\"1.1.0\",\"cardinality\":\"many\"}" }; }
25
26pub const DESCRIBE_OPERATION: &str = "describe";
27pub const HANDLE_OPERATION: &str = "handle";
28
29pub use lenso_contract_runtime::{Bytes, UnknownDomainError};
30use lenso_contract_runtime::{decode_portable_json, encode_portable_json};
31
32#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
33pub struct DescribeRequest {
34
35}
36
37#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
38pub struct DescribeResponse {
39 #[serde(rename = "routes")]
40 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
41 pub routes: Vec<DescribeResponseRoutesItem>,
42}
43
44#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
45pub struct DescribeResponseRoutesItem {
46 #[serde(rename = "method")]
47 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
48 pub method: String,
49 #[serde(rename = "openapi")]
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub openapi: Option<std::collections::BTreeMap<String, serde_json::Value>>,
52 #[serde(rename = "path")]
53 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
54 pub path: String,
55 #[serde(rename = "route_id")]
56 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
57 pub route_id: String,
58}
59
60#[derive(Clone, Debug, PartialEq)]
61pub enum DescribeError {
62 InvalidConfiguration,
63 Unknown(UnknownDomainError),
64}
65
66#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
67pub struct HandleRequest {
68 #[serde(rename = "body")]
69 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
70 pub body: Bytes,
71 #[serde(rename = "credential")]
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub credential: Option<HandleRequestCredential>,
74 #[serde(rename = "headers")]
75 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
76 pub headers: Vec<HandleRequestHeadersItem>,
77 #[serde(rename = "method")]
78 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
79 pub method: String,
80 #[serde(rename = "path")]
81 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
82 pub path: String,
83 #[serde(rename = "path_parameters")]
84 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
85 pub path_parameters: Vec<HandleRequestPathParametersItem>,
86 #[serde(rename = "query")]
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub query: Option<String>,
89 #[serde(rename = "request_id")]
90 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
91 pub request_id: String,
92 #[serde(rename = "route_id")]
93 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
94 pub route_id: String,
95}
96
97#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
98pub struct HandleRequestCredential {
99 #[serde(rename = "scheme")]
100 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
101 pub scheme: String,
102 #[serde(rename = "value")]
103 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
104 pub value: String,
105}
106
107#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
108pub struct HandleRequestHeadersItem {
109 #[serde(rename = "name")]
110 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
111 pub name: String,
112 #[serde(rename = "value")]
113 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
114 pub value: String,
115}
116
117#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
118pub struct HandleRequestPathParametersItem {
119 #[serde(rename = "name")]
120 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
121 pub name: String,
122 #[serde(rename = "value")]
123 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
124 pub value: String,
125}
126
127#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
128pub struct HandleResponse {
129 #[serde(rename = "body")]
130 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
131 pub body: Bytes,
132 #[serde(rename = "headers")]
133 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
134 pub headers: Vec<HandleResponseHeadersItem>,
135 #[serde(rename = "status")]
136 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
137 pub status: i64,
138}
139
140#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
141pub struct HandleResponseHeadersItem {
142 #[serde(rename = "name")]
143 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
144 pub name: String,
145 #[serde(rename = "value")]
146 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
147 pub value: String,
148}
149
150#[derive(Clone, Debug, PartialEq)]
151pub enum HandleError {
152 Rejected,
153 Unknown(UnknownDomainError),
154}
155
156#[derive(Debug)]
157pub struct EndpointDescribe;
158impl RequestCapability for EndpointDescribe {
159 type Request = DescribeRequest;
160 type Response = DescribeResponse;
161 type DomainError = DescribeError;
162 const ID: &'static str = CAPABILITY_ID;
163 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
164
165 fn invoke_native(endpoint: &dyn NativeRequestEndpoint, operation: &str, request: Self::Request, context: InvocationContext) -> NativeRequestFuture<Self> {
166 if operation != DESCRIBE_OPERATION {
167 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
168 }
169 let Some(typed_endpoint) = endpoint
170 .typed_endpoint()
171 .and_then(|endpoint| endpoint.downcast_ref::<EndpointRequestEndpoint>())
172 else {
173 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
174 };
175 Rc::clone(&typed_endpoint.provider).describe(context, request)
176 }
177}
178
179#[derive(Debug)]
180pub struct EndpointHandle;
181impl RequestCapability for EndpointHandle {
182 type Request = HandleRequest;
183 type Response = HandleResponse;
184 type DomainError = HandleError;
185 const ID: &'static str = CAPABILITY_ID;
186 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
187
188 fn invoke_native(endpoint: &dyn NativeRequestEndpoint, operation: &str, request: Self::Request, context: InvocationContext) -> NativeRequestFuture<Self> {
189 if operation != HANDLE_OPERATION {
190 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
191 }
192 let Some(typed_endpoint) = endpoint
193 .typed_endpoint()
194 .and_then(|endpoint| endpoint.downcast_ref::<EndpointRequestEndpoint>())
195 else {
196 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
197 };
198 Rc::clone(&typed_endpoint.provider).handle(context, request)
199 }
200}
201
202impl serde::Serialize for DescribeError {
203 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
204 where
205 S: serde::Serializer,
206 {
207 use serde::ser::SerializeMap;
208 match self {
209 Self::InvalidConfiguration => serializer.serialize_str("invalid_configuration"),
210 Self::Unknown(value) => {
211 let mut map = serializer.serialize_map(Some(1 + usize::from(value.payload.is_some()) + value.extra.len()))?;
212 map.serialize_entry("code", &value.code)?;
213 if let Some(payload) = &value.payload {
214 map.serialize_entry("payload", payload)?;
215 }
216 for (key, extra) in &value.extra {
217 map.serialize_entry(key, extra)?;
218 }
219 map.end()
220 },
221 }
222 }
223}
224
225impl<'de> serde::Deserialize<'de> for DescribeError {
226 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227 where
228 D: serde::Deserializer<'de>,
229 {
230 let value = <serde_json::Value as serde::Deserialize>::deserialize(deserializer)?;
231 match value {
232 serde_json::Value::String(code) => match code.as_str() {
233 "invalid_configuration" => Ok(Self::InvalidConfiguration),
234 _ => Ok(Self::Unknown(UnknownDomainError { code, payload: None, extra: std::collections::BTreeMap::new() })),
235 },
236 serde_json::Value::Object(mut object) => {
237 let Some(code) = object.remove("code").and_then(|value| value.as_str().map(ToOwned::to_owned)) else {
238 return Err(serde::de::Error::custom("Domain Error object is missing a string code"));
239 };
240 let payload = object.remove("payload");
241 let extra = object.into_iter().collect::<std::collections::BTreeMap<_, _>>();
242 Ok(Self::Unknown(UnknownDomainError { code, payload, extra }))
243 }
244 other => Err(serde::de::Error::custom(format!("Domain Error must be a string or object, got {other}"))),
245 }
246 }
247}
248
249impl serde::Serialize for HandleError {
250 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
251 where
252 S: serde::Serializer,
253 {
254 use serde::ser::SerializeMap;
255 match self {
256 Self::Rejected => serializer.serialize_str("rejected"),
257 Self::Unknown(value) => {
258 let mut map = serializer.serialize_map(Some(1 + usize::from(value.payload.is_some()) + value.extra.len()))?;
259 map.serialize_entry("code", &value.code)?;
260 if let Some(payload) = &value.payload {
261 map.serialize_entry("payload", payload)?;
262 }
263 for (key, extra) in &value.extra {
264 map.serialize_entry(key, extra)?;
265 }
266 map.end()
267 },
268 }
269 }
270}
271
272impl<'de> serde::Deserialize<'de> for HandleError {
273 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
274 where
275 D: serde::Deserializer<'de>,
276 {
277 let value = <serde_json::Value as serde::Deserialize>::deserialize(deserializer)?;
278 match value {
279 serde_json::Value::String(code) => match code.as_str() {
280 "rejected" => Ok(Self::Rejected),
281 _ => Ok(Self::Unknown(UnknownDomainError { code, payload: None, extra: std::collections::BTreeMap::new() })),
282 },
283 serde_json::Value::Object(mut object) => {
284 let Some(code) = object.remove("code").and_then(|value| value.as_str().map(ToOwned::to_owned)) else {
285 return Err(serde::de::Error::custom("Domain Error object is missing a string code"));
286 };
287 let payload = object.remove("payload");
288 let extra = object.into_iter().collect::<std::collections::BTreeMap<_, _>>();
289 Ok(Self::Unknown(UnknownDomainError { code, payload, extra }))
290 }
291 other => Err(serde::de::Error::custom(format!("Domain Error must be a string or object, got {other}"))),
292 }
293 }
294}
295
296pub fn encode_describe_request(value: &DescribeRequest) -> Result<String, serde_json::Error> { encode_portable_json(value) }
297pub fn decode_describe_request(wire: &str) -> Result<DescribeRequest, serde_json::Error> { decode_portable_json(wire) }
298pub fn encode_describe_response(value: &DescribeResponse) -> Result<String, serde_json::Error> { encode_portable_json(value) }
299pub fn decode_describe_response(wire: &str) -> Result<DescribeResponse, serde_json::Error> { decode_portable_json(wire) }
300pub fn encode_describe_error(value: &DescribeError) -> Result<String, serde_json::Error> { encode_portable_json(value) }
301pub fn decode_describe_error(wire: &str) -> Result<DescribeError, serde_json::Error> { decode_portable_json(wire) }
302
303pub fn encode_handle_request(value: &HandleRequest) -> Result<String, serde_json::Error> { encode_portable_json(value) }
304pub fn decode_handle_request(wire: &str) -> Result<HandleRequest, serde_json::Error> { decode_portable_json(wire) }
305pub fn encode_handle_response(value: &HandleResponse) -> Result<String, serde_json::Error> { encode_portable_json(value) }
306pub fn decode_handle_response(wire: &str) -> Result<HandleResponse, serde_json::Error> { decode_portable_json(wire) }
307pub fn encode_handle_error(value: &HandleError) -> Result<String, serde_json::Error> { encode_portable_json(value) }
308pub fn decode_handle_error(wire: &str) -> Result<HandleError, serde_json::Error> { decode_portable_json(wire) }
309
310#[doc(hidden)]
311pub trait __LensoIntoEndpointDescribeResult {
312 fn __lenso_into_result(self) -> Result<Result<DescribeResponse, DescribeError>, RuntimeFailure>;
313}
314impl __LensoIntoEndpointDescribeResult for Result<DescribeResponse, DescribeError> {
315 fn __lenso_into_result(self) -> Result<Result<DescribeResponse, DescribeError>, RuntimeFailure> { Ok(self) }
316}
317impl __LensoIntoEndpointDescribeResult for Result<Result<DescribeResponse, DescribeError>, RuntimeFailure> {
318 fn __lenso_into_result(self) -> Result<Result<DescribeResponse, DescribeError>, RuntimeFailure> { self }
319}
320impl __LensoIntoEndpointDescribeResult for Result<DescribeResponse, lenso_plugin_authoring::PluginError<DescribeError, RuntimeFailure>> {
321 fn __lenso_into_result(self) -> Result<Result<DescribeResponse, DescribeError>, RuntimeFailure> {
322 match self {
323 Ok(value) => Ok(Ok(value)),
324 Err(lenso_plugin_authoring::PluginError::Domain(error)) => Ok(Err(error)),
325 Err(lenso_plugin_authoring::PluginError::Runtime(error)) => Err(error),
326 }
327 }
328}
329impl __LensoIntoEndpointDescribeResult for Result<DescribeResponse, EndpointDescribeInvocationError> {
330 fn __lenso_into_result(self) -> Result<Result<DescribeResponse, DescribeError>, RuntimeFailure> {
331 match self {
332 Ok(value) => Ok(Ok(value)),
333 Err(EndpointDescribeInvocationError::Domain(error)) => Ok(Err(error)),
334 Err(EndpointDescribeInvocationError::Runtime(error)) => Err(error),
335 }
336 }
337}
338
339#[doc(hidden)]
340pub trait __LensoIntoEndpointHandleResult {
341 fn __lenso_into_result(self) -> Result<Result<HandleResponse, HandleError>, RuntimeFailure>;
342}
343impl __LensoIntoEndpointHandleResult for Result<HandleResponse, HandleError> {
344 fn __lenso_into_result(self) -> Result<Result<HandleResponse, HandleError>, RuntimeFailure> { Ok(self) }
345}
346impl __LensoIntoEndpointHandleResult for Result<Result<HandleResponse, HandleError>, RuntimeFailure> {
347 fn __lenso_into_result(self) -> Result<Result<HandleResponse, HandleError>, RuntimeFailure> { self }
348}
349impl __LensoIntoEndpointHandleResult for Result<HandleResponse, lenso_plugin_authoring::PluginError<HandleError, RuntimeFailure>> {
350 fn __lenso_into_result(self) -> Result<Result<HandleResponse, HandleError>, RuntimeFailure> {
351 match self {
352 Ok(value) => Ok(Ok(value)),
353 Err(lenso_plugin_authoring::PluginError::Domain(error)) => Ok(Err(error)),
354 Err(lenso_plugin_authoring::PluginError::Runtime(error)) => Err(error),
355 }
356 }
357}
358impl __LensoIntoEndpointHandleResult for Result<HandleResponse, EndpointHandleInvocationError> {
359 fn __lenso_into_result(self) -> Result<Result<HandleResponse, HandleError>, RuntimeFailure> {
360 match self {
361 Ok(value) => Ok(Ok(value)),
362 Err(EndpointHandleInvocationError::Domain(error)) => Ok(Err(error)),
363 Err(EndpointHandleInvocationError::Runtime(error)) => Err(error),
364 }
365 }
366}
367
368pub trait EndpointProvider: fmt::Debug + 'static {
369 fn describe(&self, context: InvocationContext, request: DescribeRequest) -> NativeRequestFuture<EndpointDescribe>;
370 fn handle(&self, context: InvocationContext, request: HandleRequest) -> NativeRequestFuture<EndpointHandle>;
371}
372
373#[doc(hidden)]
374#[macro_export]
375macro_rules! __lenso_native_lower_endpoint {
376 ($plugin:ty, $support:path) => {
377 use $support as __LensoNativeSupportEndpoint;
378 impl $crate::EndpointProvider for $plugin {
379 fn describe(&self, context: __LensoNativeSupportEndpoint::InvocationContext, request: $crate::DescribeRequest) -> __LensoNativeSupportEndpoint::NativeRequestFuture<$crate::EndpointDescribe> {
380 let plugin = self.clone();
381 ::std::boxed::Box::pin(async move {
382 let result = <$plugin>::describe(&plugin, context, request).await;
383 $crate::__LensoIntoEndpointDescribeResult::__lenso_into_result(result)
384 })
385 }
386 fn handle(&self, context: __LensoNativeSupportEndpoint::InvocationContext, request: $crate::HandleRequest) -> __LensoNativeSupportEndpoint::NativeRequestFuture<$crate::EndpointHandle> {
387 let plugin = self.clone();
388 ::std::boxed::Box::pin(async move {
389 let result = <$plugin>::handle(&plugin, context, request).await;
390 $crate::__LensoIntoEndpointHandleResult::__lenso_into_result(result)
391 })
392 }
393 }
394 };
395}
396
397#[derive(Debug)]
398struct EndpointRequestEndpoint { provider: Rc<dyn EndpointProvider> }
399
400#[derive(Debug)]
401pub struct EndpointEndpoint<P: EndpointProvider> { provider: Rc<P>, request_endpoint: EndpointRequestEndpoint }
402impl<P: EndpointProvider> EndpointEndpoint<P> {
403 pub fn new(provider: P) -> Self {
404 let provider = Rc::new(provider);
405 let request_provider: Rc<dyn EndpointProvider> = provider.clone();
406 Self { provider, request_endpoint: EndpointRequestEndpoint { provider: request_provider } }
407 }
408}
409
410impl<P: EndpointProvider> NativeRequestEndpoint for EndpointEndpoint<P> {
411 fn capability_id(&self) -> &'static str { CAPABILITY_ID }
412 fn descriptor_version(&self) -> &'static str { DESCRIPTOR_VERSION }
413 fn operations(&self) -> &'static [&'static str] { &[
414 DESCRIBE_OPERATION,
415 HANDLE_OPERATION,
416 ] }
417 fn typed_endpoint(&self) -> Option<&dyn std::any::Any> { Some(&self.request_endpoint) }
418 fn invoke(&self, operation: &str, request: Box<dyn std::any::Any>, context: InvocationContext) -> LocalBoxFuture<'static, Result<Result<Box<dyn std::any::Any>, Box<dyn std::any::Any>>, RuntimeFailure>> {
419 match operation {
420 DESCRIBE_OPERATION => {
421 let Ok(request) = request.downcast::<DescribeRequest>() else {
422 return Box::pin(futures::future::ready(Err(RuntimeFailure::ProtocolViolation { capability: CAPABILITY_ID })));
423 };
424 let invocation = Rc::clone(&self.provider).describe(context, *request);
425 Box::pin(async move {
426 invocation.await.map(|result| {
427 result
428 .map(|value| Box::new(value) as Box<dyn std::any::Any>)
429 .map_err(|error| Box::new(error) as Box<dyn std::any::Any>)
430 })
431 })
432 },
433 HANDLE_OPERATION => {
434 let Ok(request) = request.downcast::<HandleRequest>() else {
435 return Box::pin(futures::future::ready(Err(RuntimeFailure::ProtocolViolation { capability: CAPABILITY_ID })));
436 };
437 let invocation = Rc::clone(&self.provider).handle(context, *request);
438 Box::pin(async move {
439 invocation.await.map(|result| {
440 result
441 .map(|value| Box::new(value) as Box<dyn std::any::Any>)
442 .map_err(|error| Box::new(error) as Box<dyn std::any::Any>)
443 })
444 })
445 }
446 _ => Box::pin(futures::future::ready(Err(RuntimeFailure::UnknownOperation { capability: CAPABILITY_ID, operation: operation.to_owned() }))),
447 }
448 }
449}
450
451#[doc(hidden)]
452#[macro_export]
453macro_rules! __lenso_native_endpoints_endpoint {
454 ($provider:expr, $support:path) => {{
455 use $support as __LensoNativeSupport;
456 let endpoint = ::std::rc::Rc::new($crate::EndpointEndpoint::new($provider));
457 (
458 vec![endpoint.clone() as ::std::rc::Rc<dyn __LensoNativeSupport::NativeRequestEndpoint>],
459 vec![],
460 vec![],
461 )
462 }};
463}
464
465#[doc(hidden)]
466#[macro_export]
467macro_rules! __lenso_native_provide_endpoint {
468 ($provider:expr, $lifecycle:expr, $support:path) => {{
469 use $support as __LensoNativeSupport;
470 let (request_endpoints, stream_endpoints, event_endpoints) =
471 $crate::__lenso_native_endpoints_endpoint!($provider, $support);
472 __LensoNativeSupport::NativePluginInstance::with_all_endpoints(
473 request_endpoints,
474 stream_endpoints,
475 event_endpoints,
476 $lifecycle,
477 )
478 }};
479}
480
481#[derive(Debug)]
482pub struct EndpointClient {
483 describe: NativeRequestHandle<EndpointDescribe>,
484 handle: NativeRequestHandle<EndpointHandle>,
485}
486impl EndpointClient {
487 pub fn from_dependencies(dependencies: &PluginDependencies) -> Result<Self, RuntimeFailure> {
488 <Self as CapabilityClient>::from_dependencies(dependencies)
489 }
490
491 pub async fn describe(&self, request: DescribeRequest) -> Result<DescribeResponse, EndpointDescribeInvocationError> {
492 self.describe.invoke(DESCRIBE_OPERATION, request).await
493 .map_err(EndpointDescribeInvocationError::Runtime)?
494 .map_err(EndpointDescribeInvocationError::Domain)
495 }
496
497 pub async fn describe_with_context(&self, context: InvocationContext, request: DescribeRequest) -> Result<DescribeResponse, EndpointDescribeInvocationError> {
498 self.describe.invoke_with_context(DESCRIBE_OPERATION, context, request).await
499 .map_err(EndpointDescribeInvocationError::Runtime)?
500 .map_err(EndpointDescribeInvocationError::Domain)
501 }
502
503 pub async fn handle(&self, request: HandleRequest) -> Result<HandleResponse, EndpointHandleInvocationError> {
504 self.handle.invoke(HANDLE_OPERATION, request).await
505 .map_err(EndpointHandleInvocationError::Runtime)?
506 .map_err(EndpointHandleInvocationError::Domain)
507 }
508
509 pub async fn handle_with_context(&self, context: InvocationContext, request: HandleRequest) -> Result<HandleResponse, EndpointHandleInvocationError> {
510 self.handle.invoke_with_context(HANDLE_OPERATION, context, request).await
511 .map_err(EndpointHandleInvocationError::Runtime)?
512 .map_err(EndpointHandleInvocationError::Domain)
513 }
514}
515
516impl CapabilityClient for EndpointClient {
517 type Dependencies = PluginDependencies;
518 type Error = RuntimeFailure;
519
520 const CAPABILITY_ID: &'static str = CAPABILITY_ID;
521 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
522
523 fn from_dependencies(dependencies: &PluginDependencies) -> Result<Self, RuntimeFailure> {
524 Ok(Self {
525 describe: dependencies.one::<EndpointDescribe>()?,
526 handle: dependencies.one::<EndpointHandle>()?,
527 })
528 }
529
530 fn already_connected() -> RuntimeFailure {
531 RuntimeFailure::PluginFailure {
532 detail: format!("Capability Port {CAPABILITY_ID} was connected more than once"),
533 }
534 }
535}
536
537impl CapabilityClientMany for EndpointClient {
538 fn many_from_dependencies(
539 dependencies: &PluginDependencies,
540 ) -> Result<Vec<BoundCapabilityClient<Self>>, RuntimeFailure> {
541 dependencies
542 .bindings()
543 .iter()
544 .filter(|binding| binding.capability_id() == CAPABILITY_ID)
545 .map(|binding| {
546 Ok(BoundCapabilityClient::new(
547 binding.provider_instance(),
548 Self {
549 describe: binding.handle().ok_or(RuntimeFailure::Unavailable { capability: CAPABILITY_ID })?.typed::<EndpointDescribe>()?,
550 handle: binding.handle().ok_or(RuntimeFailure::Unavailable { capability: CAPABILITY_ID })?.typed::<EndpointHandle>()?,
551 },
552 ))
553 })
554 .collect()
555 }
556}
557
558#[derive(Clone, Debug, PartialEq)]
559pub enum EndpointDescribeInvocationError {
560 Domain(DescribeError),
561 Runtime(RuntimeFailure),
562}
563#[derive(Clone, Debug, PartialEq)]
564pub enum EndpointHandleInvocationError {
565 Domain(HandleError),
566 Runtime(RuntimeFailure),
567}