harmos_sdk/operations/
calls.rs1use std::any::{Any, TypeId};
18use std::future::Future;
19use std::pin::Pin;
20use std::sync::Arc;
21
22use super::response::ErasedResponse;
26use super::{CacheKey, OperationDeclaration, OperationDefinition, Response};
27use crate::{Message, MessageError};
28
29pub type CallFuture<'a> = Pin<Box<dyn Future<Output = Result<ErasedResponse, InvocationError>> + Send + 'a>>;
36
37#[derive(Clone)]
41pub struct Calls(pub Arc<dyn Caller>);
42
43#[derive(Clone, Copy)]
45pub struct Target {
46 pub id: &'static str,
47 pub definition: fn() -> OperationDefinition,
48 pub request: fn() -> TypeId,
49 pub memory: fn(&(dyn Any + Send)) -> usize,
50 pub response: fn() -> TypeId,
51 pub encode: fn(&(dyn Any + Send)) -> Option<Vec<u8>>,
52 pub decode: fn(&[u8]) -> Result<ErasedResponse, MessageError>,
53 pub grant: fn(&(dyn Any + Send)) -> Option<crate::plugin::Grant>,
54 pub key: fn(&(dyn Any + Send)) -> Option<CacheKey>,
55}
56
57#[derive(Debug, thiserror::Error)]
60pub enum InvocationError {
61 #[error("operation `{operation}` cannot be invoked from this carrier")]
62 Unavailable { operation: &'static str },
63
64 #[error("operation `{operation}` answered a response of another type")]
65 Response { operation: &'static str },
66
67 #[error("operation `{operation}` failed: {source}")]
68 Failed { operation: &'static str, source: Arc<dyn std::error::Error + Send + Sync> },
69}
70
71pub trait Caller: Send + Sync + 'static {
75 fn call(&self, target: Target, request: Box<dyn Any + Send>) -> CallFuture<'_>;
76}
77
78impl Target {
81 pub fn of<T: OperationDeclaration>() -> Self {
82 Self {
83 id: T::ID,
84 definition: T::definition,
85 request: TypeId::of::<T::Request>,
86 memory: |request| request.downcast_ref::<T::Request>().map_or(0, crate::MemorySize::memory_size),
87 response: TypeId::of::<T::Response>,
88 encode: |request| request.downcast_ref::<T::Request>().map(Message::encode),
89 decode: decode::<T>,
90 grant: |request| request.downcast_ref::<T::Request>().and_then(T::grant),
91 key: |request| request.downcast_ref::<T::Request>().and_then(T::key),
92 }
93 }
94}
95
96impl InvocationError {
97 pub fn failed(operation: &'static str, source: impl std::error::Error + Send + Sync + 'static) -> Self {
98 Self::Failed { operation, source: Arc::new(source) }
99 }
100}
101
102fn decode<T: OperationDeclaration>(bytes: &[u8]) -> Result<ErasedResponse, MessageError> {
107 let response = T::Response::decode(bytes)?;
108 Ok(Response::new(response).into_erased())
109}
110
111