1#[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}