golem_api_grpc/
lib.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://license.golem.cloud/LICENSE
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(test)]
16test_r::enable!();
17
18#[allow(clippy::large_enum_variant)]
19pub mod proto {
20    use self::golem::worker::{WasiConfigVars, WasiConfigVarsEntry};
21    use crate::proto::golem::worker::UpdateMode;
22    use bincode::de::Decoder;
23    use bincode::enc::Encoder;
24    use bincode::error::{DecodeError, EncodeError};
25    use bincode::{Decode, Encode};
26    use golem_wasm_ast::analysis::{
27        AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
28        AnalysedInstance,
29    };
30    use std::collections::BTreeMap;
31    use uuid::Uuid;
32
33    tonic::include_proto!("mod");
34
35    pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("services");
36
37    impl From<Uuid> for golem::common::Uuid {
38        fn from(value: Uuid) -> Self {
39            let (high_bits, low_bits) = value.as_u64_pair();
40            golem::common::Uuid {
41                high_bits,
42                low_bits,
43            }
44        }
45    }
46
47    impl From<golem::common::Uuid> for Uuid {
48        fn from(value: golem::common::Uuid) -> Self {
49            let high_bits = value.high_bits;
50            let low_bits = value.low_bits;
51            Uuid::from_u64_pair(high_bits, low_bits)
52        }
53    }
54
55    impl TryFrom<crate::proto::golem::component::FunctionResult> for AnalysedFunctionResult {
56        type Error = String;
57
58        fn try_from(
59            value: crate::proto::golem::component::FunctionResult,
60        ) -> Result<Self, Self::Error> {
61            Ok(Self {
62                typ: (&value.typ.ok_or("Missing typ")?).try_into()?,
63            })
64        }
65    }
66
67    impl From<AnalysedFunctionResult> for crate::proto::golem::component::FunctionResult {
68        fn from(value: AnalysedFunctionResult) -> Self {
69            Self {
70                typ: Some((&value.typ).into()),
71            }
72        }
73    }
74
75    impl TryFrom<crate::proto::golem::component::ExportInstance> for AnalysedInstance {
76        type Error = String;
77
78        fn try_from(
79            value: crate::proto::golem::component::ExportInstance,
80        ) -> Result<Self, Self::Error> {
81            Ok(Self {
82                name: value.name,
83                functions: value
84                    .functions
85                    .into_iter()
86                    .map(|function| function.try_into())
87                    .collect::<Result<_, _>>()?,
88            })
89        }
90    }
91
92    impl From<AnalysedInstance> for crate::proto::golem::component::ExportInstance {
93        fn from(value: AnalysedInstance) -> Self {
94            Self {
95                name: value.name,
96                functions: value
97                    .functions
98                    .into_iter()
99                    .map(|function| function.into())
100                    .collect(),
101            }
102        }
103    }
104
105    impl TryFrom<crate::proto::golem::component::ExportFunction> for AnalysedFunction {
106        type Error = String;
107
108        fn try_from(
109            value: crate::proto::golem::component::ExportFunction,
110        ) -> Result<Self, Self::Error> {
111            Ok(Self {
112                name: value.name,
113                parameters: value
114                    .parameters
115                    .into_iter()
116                    .map(|parameter| parameter.try_into())
117                    .collect::<Result<_, _>>()?,
118                result: value.result.map(|result| result.try_into()).transpose()?,
119            })
120        }
121    }
122
123    impl From<AnalysedFunction> for crate::proto::golem::component::ExportFunction {
124        fn from(value: AnalysedFunction) -> Self {
125            Self {
126                name: value.name,
127                parameters: value
128                    .parameters
129                    .into_iter()
130                    .map(|parameter| parameter.into())
131                    .collect(),
132                result: value.result.map(|result| result.into()),
133            }
134        }
135    }
136
137    impl TryFrom<crate::proto::golem::component::Export> for AnalysedExport {
138        type Error = String;
139
140        fn try_from(value: crate::proto::golem::component::Export) -> Result<Self, Self::Error> {
141            match value.export {
142                None => Err("Missing export".to_string()),
143                Some(crate::proto::golem::component::export::Export::Instance(instance)) => {
144                    Ok(Self::Instance(instance.try_into()?))
145                }
146                Some(crate::proto::golem::component::export::Export::Function(function)) => {
147                    Ok(Self::Function(function.try_into()?))
148                }
149            }
150        }
151    }
152
153    impl From<AnalysedExport> for crate::proto::golem::component::Export {
154        fn from(value: AnalysedExport) -> Self {
155            match value {
156                AnalysedExport::Instance(instance) => Self {
157                    export: Some(crate::proto::golem::component::export::Export::Instance(
158                        instance.into(),
159                    )),
160                },
161                AnalysedExport::Function(function) => Self {
162                    export: Some(crate::proto::golem::component::export::Export::Function(
163                        function.into(),
164                    )),
165                },
166            }
167        }
168    }
169
170    impl TryFrom<golem::component::FunctionParameter> for AnalysedFunctionParameter {
171        type Error = String;
172
173        fn try_from(
174            value: crate::proto::golem::component::FunctionParameter,
175        ) -> Result<Self, Self::Error> {
176            Ok(Self {
177                name: value.name,
178                typ: (&value.typ.ok_or("Missing typ")?).try_into()?,
179            })
180        }
181    }
182
183    impl From<AnalysedFunctionParameter> for crate::proto::golem::component::FunctionParameter {
184        fn from(value: AnalysedFunctionParameter) -> Self {
185            Self {
186                name: value.name,
187                typ: Some((&value.typ).into()),
188            }
189        }
190    }
191
192    impl Encode for UpdateMode {
193        fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
194            match self {
195                UpdateMode::Automatic => 0u8.encode(encoder),
196                UpdateMode::Manual => 1u8.encode(encoder),
197            }
198        }
199    }
200
201    impl<Context> Decode<Context> for UpdateMode {
202        fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
203            match Decode::decode(decoder)? {
204                0u8 => Ok(UpdateMode::Automatic),
205                1u8 => Ok(UpdateMode::Manual),
206                _ => Err(DecodeError::Other("Invalid UpdateMode")),
207            }
208        }
209    }
210
211    impl From<BTreeMap<String, String>> for WasiConfigVars {
212        fn from(value: BTreeMap<String, String>) -> Self {
213            Self {
214                entries: value
215                    .into_iter()
216                    .map(|(key, value)| WasiConfigVarsEntry { key, value })
217                    .collect(),
218            }
219        }
220    }
221
222    impl From<WasiConfigVars> for BTreeMap<String, String> {
223        fn from(value: WasiConfigVars) -> Self {
224            value
225                .entries
226                .into_iter()
227                .map(|e| (e.key, e.value))
228                .collect()
229        }
230    }
231
232    #[cfg(test)]
233    mod tests {
234        use crate::proto::golem;
235        use prost::Message;
236        use test_r::test;
237
238        #[test]
239        fn target_worker_id_and_worker_id_are_bin_compatible() {
240            let component_id_uuid = uuid::Uuid::new_v4();
241            let component_id_uuid: golem::common::Uuid = component_id_uuid.into();
242            let component_id = golem::component::ComponentId {
243                value: Some(component_id_uuid),
244            };
245            let target_worker_id = golem::worker::TargetWorkerId {
246                component_id: Some(component_id),
247                name: Some("hello".to_string()),
248            };
249            let worker_id = golem::worker::WorkerId {
250                component_id: Some(component_id),
251                name: "hello".to_string(),
252            };
253
254            let target_worker_id_bytes = target_worker_id.encode_to_vec();
255            let worker_id_bytes = worker_id.encode_to_vec();
256
257            assert_eq!(target_worker_id_bytes, worker_id_bytes);
258        }
259    }
260}