stellation_bridge/registry/
routine.rs

1use std::any::TypeId;
2use std::fmt;
3use std::rc::Rc;
4use std::sync::Arc;
5
6use super::Incoming;
7use crate::routines::{BridgedMutation, BridgedQuery, MutationResult, QueryResult};
8use crate::{BridgeError, BridgeResult};
9
10/// The Registry Builder for Routine Registry
11#[derive(Default)]
12pub struct RoutineRegistryBuilder {
13    query_ids: Vec<TypeId>,
14}
15
16impl fmt::Debug for RoutineRegistryBuilder {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.debug_struct("RoutineRegistryBuilder")
19            .finish_non_exhaustive()
20    }
21}
22
23impl RoutineRegistryBuilder {
24    /// Creates a registry builder.
25    pub fn new() -> Self {
26        Self::default()
27    }
28
29    /// Creates a registry.
30    pub fn build(self) -> RoutineRegistry {
31        RoutineRegistry {
32            inner: Arc::new(self),
33        }
34    }
35
36    /// Adds a mutation.
37    pub fn add_mutation<T>(mut self) -> Self
38    where
39        T: 'static + BridgedMutation,
40    {
41        let type_id = TypeId::of::<T>();
42        self.query_ids.push(type_id);
43
44        self
45    }
46
47    /// Adds a query.
48    pub fn add_query<T>(mut self) -> Self
49    where
50        T: 'static + BridgedQuery,
51    {
52        let type_id = TypeId::of::<T>();
53        self.query_ids.push(type_id);
54
55        self
56    }
57}
58
59/// The Registry that holds available queries and mutations.
60pub struct RoutineRegistry {
61    inner: Arc<RoutineRegistryBuilder>,
62}
63
64impl fmt::Debug for RoutineRegistry {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        f.debug_struct("RoutineRegistry").finish_non_exhaustive()
67    }
68}
69
70impl PartialEq for RoutineRegistry {
71    fn eq(&self, other: &Self) -> bool {
72        Arc::ptr_eq(&self.inner, &other.inner)
73    }
74}
75
76impl Eq for RoutineRegistry {}
77
78impl Clone for RoutineRegistry {
79    fn clone(&self) -> Self {
80        Self {
81            inner: self.inner.clone(),
82        }
83    }
84}
85
86impl RoutineRegistry {
87    /// Creates a Builder for remote registry.
88    pub fn builder() -> RoutineRegistryBuilder {
89        RoutineRegistryBuilder::new()
90    }
91
92    /// The method to encode the query input for a remote link.
93    pub(crate) fn encode_query_input<T>(&self, input: &T::Input) -> BridgeResult<Vec<u8>>
94    where
95        T: 'static + BridgedQuery,
96    {
97        let input = bincode::serialize(&input).map_err(BridgeError::Encoding)?;
98        let type_id = TypeId::of::<T>();
99
100        let query_index = self
101            .inner
102            .query_ids
103            .iter()
104            .enumerate()
105            .find(|(_, m)| **m == type_id)
106            .ok_or(BridgeError::InvalidType(type_id))?
107            .0;
108
109        let incoming = Incoming {
110            query_index,
111            input: &input,
112        };
113
114        bincode::serialize(&incoming).map_err(BridgeError::Encoding)
115    }
116
117    /// The method to decode the query output for a remote link.
118    pub(crate) fn decode_query_output<T>(&self, output: &[u8]) -> QueryResult<T>
119    where
120        T: 'static + BridgedQuery,
121    {
122        bincode::deserialize::<std::result::Result<T, T::Error>>(output)
123            .map_err(BridgeError::Encoding)
124            .map_err(T::into_query_error)?
125            .map(Rc::new)
126    }
127
128    /// The method to encode the mutation input for a remote link.
129    pub(crate) fn encode_mutation_input<T>(&self, input: &T::Input) -> BridgeResult<Vec<u8>>
130    where
131        T: 'static + BridgedMutation,
132    {
133        let input = bincode::serialize(&input).map_err(BridgeError::Encoding)?;
134        let type_id = TypeId::of::<T>();
135
136        let query_index = self
137            .inner
138            .query_ids
139            .iter()
140            .enumerate()
141            .find(|(_, m)| **m == type_id)
142            .ok_or(BridgeError::InvalidType(type_id))?
143            .0;
144
145        let incoming = Incoming {
146            query_index,
147            input: &input,
148        };
149
150        bincode::serialize(&incoming).map_err(BridgeError::Encoding)
151    }
152
153    /// The method to decode the mutation output for a remote link.
154    pub(crate) fn decode_mutation_output<T>(&self, output: &[u8]) -> MutationResult<T>
155    where
156        T: 'static + BridgedMutation,
157    {
158        bincode::deserialize::<std::result::Result<T, T::Error>>(output)
159            .map_err(BridgeError::Encoding)
160            .map_err(T::into_mutation_error)?
161            .map(Rc::new)
162    }
163}