1use flatbuffers::{FlatBufferBuilder, InvalidFlatbuffer};
4pub use selium_abi::{
5 AbiParam, AbiScalarType, AbiScalarValue, AbiSignature, Capability, EntrypointArg,
6 GuestResourceId, GuestUint,
7};
8use thiserror::Error;
9
10#[allow(missing_docs)]
12#[allow(warnings)]
13#[rustfmt::skip]
14pub mod fbs;
15
16use crate::fbs::remote_client::protocol as fb;
17
18const REMOTE_CLIENT_IDENTIFIER: &str = "RMCL";
19
20pub type GuestWriterId = u16;
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct IoFrame {
26 pub writer_id: GuestWriterId,
28 pub payload: Vec<u8>,
30}
31
32#[derive(Clone, Debug, PartialEq)]
34pub enum Request {
35 ChannelCreate(GuestUint),
37 ChannelDelete(GuestResourceId),
39 Subscribe(ChannelRef, GuestUint),
41 Publish(GuestResourceId),
43 ProcessStart(ProcessStartRequest),
45 ProcessStop(GuestResourceId),
47 ProcessLogChannel(GuestResourceId),
49}
50
51#[derive(Clone, Debug, PartialEq)]
53pub enum Response {
54 ChannelCreate(GuestResourceId),
56 ChannelRead(IoFrame),
58 ChannelWrite(GuestUint),
60 ProcessStart(GuestResourceId),
62 ProcessLogChannel(GuestResourceId),
64 Ok,
66 Error(String),
68}
69
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
72pub enum ChannelRef {
73 Strong(GuestResourceId),
75 Shared(GuestResourceId),
77}
78
79#[derive(Clone, Debug, PartialEq)]
81pub struct ProcessStartRequest {
82 pub module_id: String,
84 pub entrypoint: String,
86 pub log_uri: Option<String>,
88 pub capabilities: Vec<Capability>,
90 pub signature: AbiSignature,
92 pub args: Vec<EntrypointArg>,
94}
95
96#[derive(Debug, Error)]
98pub enum ProtocolError {
99 #[error("invalid flatbuffer: {0:?}")]
101 InvalidFlatbuffer(InvalidFlatbuffer),
102 #[error("remote-client message missing payload")]
104 MissingPayload,
105 #[error("unknown remote-client payload type")]
107 UnknownPayload,
108 #[error("invalid remote-client message identifier")]
110 InvalidIdentifier,
111 #[error("remote-client payload was not a {expected}")]
113 UnexpectedPayload { expected: &'static str },
114 #[error("unknown capability variant")]
116 UnknownCapability,
117 #[error("unknown ABI scalar type")]
119 UnknownAbiScalarType,
120 #[error("unknown ABI parameter kind")]
122 UnknownAbiParamKind,
123 #[error("unknown channel reference kind")]
125 UnknownChannelRefKind,
126 #[error("unknown entrypoint argument kind")]
128 UnknownEntrypointArgKind,
129 #[error("missing remote-client field: {0}")]
131 MissingField(&'static str),
132}
133
134impl From<InvalidFlatbuffer> for ProtocolError {
135 fn from(value: InvalidFlatbuffer) -> Self {
136 ProtocolError::InvalidFlatbuffer(value)
137 }
138}
139
140pub fn encode_request(request: &Request) -> Result<Vec<u8>, ProtocolError> {
142 let mut builder = FlatBufferBuilder::new();
143 let (payload_type, payload) = encode_request_payload(&mut builder, request)?;
144 let message = fb::RemoteClientMessage::create(
145 &mut builder,
146 &fb::RemoteClientMessageArgs {
147 payload_type,
148 payload,
149 },
150 );
151 builder.finish(message, Some(REMOTE_CLIENT_IDENTIFIER));
152 Ok(builder.finished_data().to_vec())
153}
154
155pub fn decode_request(bytes: &[u8]) -> Result<Request, ProtocolError> {
157 let message = decode_message(bytes)?;
158
159 match message.payload_type() {
160 fb::RemoteClientPayload::ChannelCreateRequest => {
161 let req = message
162 .payload_as_channel_create_request()
163 .ok_or(ProtocolError::MissingPayload)?;
164 Ok(Request::ChannelCreate(req.capacity()))
165 }
166 fb::RemoteClientPayload::ChannelDeleteRequest => {
167 let req = message
168 .payload_as_channel_delete_request()
169 .ok_or(ProtocolError::MissingPayload)?;
170 Ok(Request::ChannelDelete(req.handle()))
171 }
172 fb::RemoteClientPayload::SubscribeRequest => {
173 let req = message
174 .payload_as_subscribe_request()
175 .ok_or(ProtocolError::MissingPayload)?;
176 let target = decode_channel_ref(
177 req.target()
178 .ok_or(ProtocolError::MissingField("subscribe.target"))?,
179 )?;
180 Ok(Request::Subscribe(target, req.chunk_size()))
181 }
182 fb::RemoteClientPayload::PublishRequest => {
183 let req = message
184 .payload_as_publish_request()
185 .ok_or(ProtocolError::MissingPayload)?;
186 Ok(Request::Publish(req.handle()))
187 }
188 fb::RemoteClientPayload::ProcessStartRequest => {
189 let req = message
190 .payload_as_process_start_request()
191 .ok_or(ProtocolError::MissingPayload)?;
192 Ok(Request::ProcessStart(decode_process_start_request(req)?))
193 }
194 fb::RemoteClientPayload::ProcessStopRequest => {
195 let req = message
196 .payload_as_process_stop_request()
197 .ok_or(ProtocolError::MissingPayload)?;
198 Ok(Request::ProcessStop(req.handle()))
199 }
200 fb::RemoteClientPayload::ProcessLogChannelRequest => {
201 let req = message
202 .payload_as_process_log_channel_request()
203 .ok_or(ProtocolError::MissingPayload)?;
204 Ok(Request::ProcessLogChannel(req.handle()))
205 }
206 fb::RemoteClientPayload::ChannelCreateResponse
207 | fb::RemoteClientPayload::ChannelReadResponse
208 | fb::RemoteClientPayload::ChannelWriteResponse
209 | fb::RemoteClientPayload::ProcessStartResponse
210 | fb::RemoteClientPayload::ProcessLogChannelResponse
211 | fb::RemoteClientPayload::OkResponse
212 | fb::RemoteClientPayload::ErrorResponse => Err(ProtocolError::UnexpectedPayload {
213 expected: "request",
214 }),
215 _ => Err(ProtocolError::UnknownPayload),
216 }
217}
218
219pub fn encode_response(response: &Response) -> Result<Vec<u8>, ProtocolError> {
221 let mut builder = FlatBufferBuilder::new();
222 let (payload_type, payload) = encode_response_payload(&mut builder, response);
223 let message = fb::RemoteClientMessage::create(
224 &mut builder,
225 &fb::RemoteClientMessageArgs {
226 payload_type,
227 payload,
228 },
229 );
230 builder.finish(message, Some(REMOTE_CLIENT_IDENTIFIER));
231 Ok(builder.finished_data().to_vec())
232}
233
234pub fn decode_response(bytes: &[u8]) -> Result<Response, ProtocolError> {
236 let message = decode_message(bytes)?;
237
238 match message.payload_type() {
239 fb::RemoteClientPayload::ChannelCreateResponse => {
240 let resp = message
241 .payload_as_channel_create_response()
242 .ok_or(ProtocolError::MissingPayload)?;
243 Ok(Response::ChannelCreate(resp.handle()))
244 }
245 fb::RemoteClientPayload::ChannelReadResponse => {
246 let resp = message
247 .payload_as_channel_read_response()
248 .ok_or(ProtocolError::MissingPayload)?;
249 let frame = resp
250 .frame()
251 .ok_or(ProtocolError::MissingField("channel_read.frame"))?;
252 Ok(Response::ChannelRead(decode_io_frame(frame)?))
253 }
254 fb::RemoteClientPayload::ChannelWriteResponse => {
255 let resp = message
256 .payload_as_channel_write_response()
257 .ok_or(ProtocolError::MissingPayload)?;
258 Ok(Response::ChannelWrite(resp.len()))
259 }
260 fb::RemoteClientPayload::ProcessStartResponse => {
261 let resp = message
262 .payload_as_process_start_response()
263 .ok_or(ProtocolError::MissingPayload)?;
264 Ok(Response::ProcessStart(resp.handle()))
265 }
266 fb::RemoteClientPayload::ProcessLogChannelResponse => {
267 let resp = message
268 .payload_as_process_log_channel_response()
269 .ok_or(ProtocolError::MissingPayload)?;
270 Ok(Response::ProcessLogChannel(resp.handle()))
271 }
272 fb::RemoteClientPayload::OkResponse => Ok(Response::Ok),
273 fb::RemoteClientPayload::ErrorResponse => {
274 let resp = message
275 .payload_as_error_response()
276 .ok_or(ProtocolError::MissingPayload)?;
277 let message = resp
278 .message()
279 .ok_or(ProtocolError::MissingField("error.message"))?
280 .to_string();
281 Ok(Response::Error(message))
282 }
283 fb::RemoteClientPayload::ChannelCreateRequest
284 | fb::RemoteClientPayload::ChannelDeleteRequest
285 | fb::RemoteClientPayload::SubscribeRequest
286 | fb::RemoteClientPayload::PublishRequest
287 | fb::RemoteClientPayload::ProcessStartRequest
288 | fb::RemoteClientPayload::ProcessStopRequest
289 | fb::RemoteClientPayload::ProcessLogChannelRequest => {
290 Err(ProtocolError::UnexpectedPayload {
291 expected: "response",
292 })
293 }
294 _ => Err(ProtocolError::UnknownPayload),
295 }
296}
297
298fn decode_message(bytes: &[u8]) -> Result<fb::RemoteClientMessage<'_>, ProtocolError> {
299 if !fb::remote_client_message_buffer_has_identifier(bytes) {
300 return Err(ProtocolError::InvalidIdentifier);
301 }
302 Ok(flatbuffers::root::<fb::RemoteClientMessage>(bytes)?)
303}
304
305fn encode_request_payload<'bldr>(
306 builder: &mut FlatBufferBuilder<'bldr>,
307 request: &Request,
308) -> Result<
309 (
310 fb::RemoteClientPayload,
311 Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>,
312 ),
313 ProtocolError,
314> {
315 let payload = match request {
316 Request::ChannelCreate(capacity) => {
317 let payload = fb::ChannelCreateRequest::create(
318 builder,
319 &fb::ChannelCreateRequestArgs {
320 capacity: *capacity,
321 },
322 );
323 (
324 fb::RemoteClientPayload::ChannelCreateRequest,
325 Some(payload.as_union_value()),
326 )
327 }
328 Request::ChannelDelete(handle) => {
329 let payload = fb::ChannelDeleteRequest::create(
330 builder,
331 &fb::ChannelDeleteRequestArgs { handle: *handle },
332 );
333 (
334 fb::RemoteClientPayload::ChannelDeleteRequest,
335 Some(payload.as_union_value()),
336 )
337 }
338 Request::Subscribe(target, chunk_size) => {
339 let target = encode_channel_ref(builder, target);
340 let payload = fb::SubscribeRequest::create(
341 builder,
342 &fb::SubscribeRequestArgs {
343 target: Some(target),
344 chunk_size: *chunk_size,
345 },
346 );
347 (
348 fb::RemoteClientPayload::SubscribeRequest,
349 Some(payload.as_union_value()),
350 )
351 }
352 Request::Publish(handle) => {
353 let payload =
354 fb::PublishRequest::create(builder, &fb::PublishRequestArgs { handle: *handle });
355 (
356 fb::RemoteClientPayload::PublishRequest,
357 Some(payload.as_union_value()),
358 )
359 }
360 Request::ProcessStart(request) => {
361 let payload = encode_process_start_request(builder, request)?;
362 (
363 fb::RemoteClientPayload::ProcessStartRequest,
364 Some(payload.as_union_value()),
365 )
366 }
367 Request::ProcessStop(handle) => {
368 let payload = fb::ProcessStopRequest::create(
369 builder,
370 &fb::ProcessStopRequestArgs { handle: *handle },
371 );
372 (
373 fb::RemoteClientPayload::ProcessStopRequest,
374 Some(payload.as_union_value()),
375 )
376 }
377 Request::ProcessLogChannel(handle) => {
378 let payload = fb::ProcessLogChannelRequest::create(
379 builder,
380 &fb::ProcessLogChannelRequestArgs { handle: *handle },
381 );
382 (
383 fb::RemoteClientPayload::ProcessLogChannelRequest,
384 Some(payload.as_union_value()),
385 )
386 }
387 };
388 Ok(payload)
389}
390
391fn encode_response_payload<'bldr>(
392 builder: &mut FlatBufferBuilder<'bldr>,
393 response: &Response,
394) -> (
395 fb::RemoteClientPayload,
396 Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>,
397) {
398 match response {
399 Response::ChannelCreate(handle) => {
400 let payload = fb::ChannelCreateResponse::create(
401 builder,
402 &fb::ChannelCreateResponseArgs { handle: *handle },
403 );
404 (
405 fb::RemoteClientPayload::ChannelCreateResponse,
406 Some(payload.as_union_value()),
407 )
408 }
409 Response::ChannelRead(frame) => {
410 let frame = encode_io_frame(builder, frame);
411 let payload = fb::ChannelReadResponse::create(
412 builder,
413 &fb::ChannelReadResponseArgs { frame: Some(frame) },
414 );
415 (
416 fb::RemoteClientPayload::ChannelReadResponse,
417 Some(payload.as_union_value()),
418 )
419 }
420 Response::ChannelWrite(len) => {
421 let payload = fb::ChannelWriteResponse::create(
422 builder,
423 &fb::ChannelWriteResponseArgs { len: *len },
424 );
425 (
426 fb::RemoteClientPayload::ChannelWriteResponse,
427 Some(payload.as_union_value()),
428 )
429 }
430 Response::ProcessStart(handle) => {
431 let payload = fb::ProcessStartResponse::create(
432 builder,
433 &fb::ProcessStartResponseArgs { handle: *handle },
434 );
435 (
436 fb::RemoteClientPayload::ProcessStartResponse,
437 Some(payload.as_union_value()),
438 )
439 }
440 Response::ProcessLogChannel(handle) => {
441 let payload = fb::ProcessLogChannelResponse::create(
442 builder,
443 &fb::ProcessLogChannelResponseArgs { handle: *handle },
444 );
445 (
446 fb::RemoteClientPayload::ProcessLogChannelResponse,
447 Some(payload.as_union_value()),
448 )
449 }
450 Response::Ok => {
451 let payload = fb::OkResponse::create(builder, &fb::OkResponseArgs {});
452 (
453 fb::RemoteClientPayload::OkResponse,
454 Some(payload.as_union_value()),
455 )
456 }
457 Response::Error(message) => {
458 let message = builder.create_string(message);
459 let payload = fb::ErrorResponse::create(
460 builder,
461 &fb::ErrorResponseArgs {
462 message: Some(message),
463 },
464 );
465 (
466 fb::RemoteClientPayload::ErrorResponse,
467 Some(payload.as_union_value()),
468 )
469 }
470 }
471}
472
473fn encode_channel_ref<'bldr>(
474 builder: &mut FlatBufferBuilder<'bldr>,
475 target: &ChannelRef,
476) -> flatbuffers::WIPOffset<fb::ChannelRef<'bldr>> {
477 let (kind, handle) = match target {
478 ChannelRef::Strong(handle) => (fb::ChannelRefKind::Strong, *handle),
479 ChannelRef::Shared(handle) => (fb::ChannelRefKind::Shared, *handle),
480 };
481
482 fb::ChannelRef::create(builder, &fb::ChannelRefArgs { kind, handle })
483}
484
485fn decode_channel_ref(channel_ref: fb::ChannelRef<'_>) -> Result<ChannelRef, ProtocolError> {
486 match channel_ref.kind() {
487 fb::ChannelRefKind::Strong => Ok(ChannelRef::Strong(channel_ref.handle())),
488 fb::ChannelRefKind::Shared => Ok(ChannelRef::Shared(channel_ref.handle())),
489 _ => Err(ProtocolError::UnknownChannelRefKind),
490 }
491}
492
493fn encode_process_start_request<'bldr>(
494 builder: &mut FlatBufferBuilder<'bldr>,
495 request: &ProcessStartRequest,
496) -> Result<flatbuffers::WIPOffset<fb::ProcessStartRequest<'bldr>>, ProtocolError> {
497 let module_id = builder.create_string(&request.module_id);
498 let entrypoint = builder.create_string(&request.entrypoint);
499 let log_uri = request
500 .log_uri
501 .as_ref()
502 .map(|value| builder.create_string(value));
503 let capabilities = encode_capabilities(builder, &request.capabilities)?;
504 let signature = encode_abi_signature(builder, &request.signature);
505 let args = encode_entrypoint_args(builder, &request.args);
506
507 Ok(fb::ProcessStartRequest::create(
508 builder,
509 &fb::ProcessStartRequestArgs {
510 module_id: Some(module_id),
511 entrypoint: Some(entrypoint),
512 log_uri,
513 capabilities: Some(capabilities),
514 signature: Some(signature),
515 args: Some(args),
516 },
517 ))
518}
519
520fn decode_process_start_request(
521 request: fb::ProcessStartRequest<'_>,
522) -> Result<ProcessStartRequest, ProtocolError> {
523 let module_id = request
524 .module_id()
525 .ok_or(ProtocolError::MissingField("process_start.module_id"))?
526 .to_string();
527 let entrypoint = request
528 .entrypoint()
529 .ok_or(ProtocolError::MissingField("process_start.entrypoint"))?
530 .to_string();
531 let log_uri = request.log_uri().map(|value| value.to_string());
532 let capabilities = decode_capabilities(request.capabilities())?;
533 let signature = request
534 .signature()
535 .ok_or(ProtocolError::MissingField("process_start.signature"))?;
536 let signature = decode_abi_signature(signature)?;
537 let args = decode_entrypoint_args(request.args())?;
538
539 Ok(ProcessStartRequest {
540 module_id,
541 entrypoint,
542 log_uri,
543 capabilities,
544 signature,
545 args,
546 })
547}
548
549fn encode_capabilities<'bldr>(
550 builder: &mut FlatBufferBuilder<'bldr>,
551 caps: &[Capability],
552) -> Result<flatbuffers::WIPOffset<flatbuffers::Vector<'bldr, fb::Capability>>, ProtocolError> {
553 let mut values = Vec::with_capacity(caps.len());
554 for cap in caps {
555 values.push(encode_capability(*cap)?);
556 }
557 Ok(builder.create_vector(&values))
558}
559
560fn decode_capabilities(
561 caps: Option<flatbuffers::Vector<'_, fb::Capability>>,
562) -> Result<Vec<Capability>, ProtocolError> {
563 let mut out = Vec::new();
564 if let Some(vec) = caps {
565 for cap in vec.iter() {
566 out.push(decode_capability(cap)?);
567 }
568 }
569 Ok(out)
570}
571
572fn encode_capability(value: Capability) -> Result<fb::Capability, ProtocolError> {
573 match value {
574 Capability::SessionLifecycle => Ok(fb::Capability::SessionLifecycle),
575 Capability::ChannelLifecycle => Ok(fb::Capability::ChannelLifecycle),
576 Capability::ChannelReader => Ok(fb::Capability::ChannelReader),
577 Capability::ChannelWriter => Ok(fb::Capability::ChannelWriter),
578 Capability::ProcessLifecycle => Ok(fb::Capability::ProcessLifecycle),
579 Capability::NetQuicBind => Ok(fb::Capability::NetQuicBind),
580 Capability::NetQuicAccept => Ok(fb::Capability::NetQuicAccept),
581 Capability::NetQuicConnect => Ok(fb::Capability::NetQuicConnect),
582 Capability::NetQuicRead => Ok(fb::Capability::NetQuicRead),
583 Capability::NetQuicWrite => Ok(fb::Capability::NetQuicWrite),
584 Capability::NetHttpBind => Ok(fb::Capability::NetHttpBind),
585 Capability::NetHttpAccept => Ok(fb::Capability::NetHttpAccept),
586 Capability::NetHttpConnect => Ok(fb::Capability::NetHttpConnect),
587 Capability::NetHttpRead => Ok(fb::Capability::NetHttpRead),
588 Capability::NetHttpWrite => Ok(fb::Capability::NetHttpWrite),
589 Capability::NetTlsServerConfig => Ok(fb::Capability::NetTlsServerConfig),
590 Capability::NetTlsClientConfig => Ok(fb::Capability::NetTlsClientConfig),
591 Capability::SingletonRegistry => Ok(fb::Capability::SingletonRegistry),
592 Capability::SingletonLookup => Ok(fb::Capability::SingletonLookup),
593 Capability::TimeRead => Ok(fb::Capability::TimeRead),
594 }
595}
596
597fn decode_capability(value: fb::Capability) -> Result<Capability, ProtocolError> {
598 match value {
599 fb::Capability::SessionLifecycle => Ok(Capability::SessionLifecycle),
600 fb::Capability::ChannelLifecycle => Ok(Capability::ChannelLifecycle),
601 fb::Capability::ChannelReader => Ok(Capability::ChannelReader),
602 fb::Capability::ChannelWriter => Ok(Capability::ChannelWriter),
603 fb::Capability::ProcessLifecycle => Ok(Capability::ProcessLifecycle),
604 fb::Capability::NetQuicBind => Ok(Capability::NetQuicBind),
605 fb::Capability::NetQuicAccept => Ok(Capability::NetQuicAccept),
606 fb::Capability::NetQuicConnect => Ok(Capability::NetQuicConnect),
607 fb::Capability::NetQuicRead => Ok(Capability::NetQuicRead),
608 fb::Capability::NetQuicWrite => Ok(Capability::NetQuicWrite),
609 fb::Capability::NetHttpBind => Ok(Capability::NetHttpBind),
610 fb::Capability::NetHttpAccept => Ok(Capability::NetHttpAccept),
611 fb::Capability::NetHttpConnect => Ok(Capability::NetHttpConnect),
612 fb::Capability::NetHttpRead => Ok(Capability::NetHttpRead),
613 fb::Capability::NetHttpWrite => Ok(Capability::NetHttpWrite),
614 fb::Capability::NetTlsServerConfig => Ok(Capability::NetTlsServerConfig),
615 fb::Capability::NetTlsClientConfig => Ok(Capability::NetTlsClientConfig),
616 fb::Capability::SingletonRegistry => Ok(Capability::SingletonRegistry),
617 fb::Capability::SingletonLookup => Ok(Capability::SingletonLookup),
618 fb::Capability::TimeRead => Ok(Capability::TimeRead),
619 _ => Err(ProtocolError::UnknownCapability),
620 }
621}
622
623fn encode_abi_signature<'bldr>(
624 builder: &mut FlatBufferBuilder<'bldr>,
625 signature: &AbiSignature,
626) -> flatbuffers::WIPOffset<fb::AbiSignature<'bldr>> {
627 let params = encode_abi_params(builder, signature.params());
628 let results = encode_abi_params(builder, signature.results());
629
630 fb::AbiSignature::create(
631 builder,
632 &fb::AbiSignatureArgs {
633 params: Some(params),
634 results: Some(results),
635 },
636 )
637}
638
639fn decode_abi_signature(signature: fb::AbiSignature<'_>) -> Result<AbiSignature, ProtocolError> {
640 let params = decode_abi_params(signature.params())?;
641 let results = decode_abi_params(signature.results())?;
642 Ok(AbiSignature::new(params, results))
643}
644
645fn encode_abi_params<'bldr>(
646 builder: &mut FlatBufferBuilder<'bldr>,
647 params: &[AbiParam],
648) -> flatbuffers::WIPOffset<
649 flatbuffers::Vector<'bldr, flatbuffers::ForwardsUOffset<fb::AbiParam<'bldr>>>,
650> {
651 let items: Vec<_> = params
652 .iter()
653 .map(|param| encode_abi_param(builder, param))
654 .collect();
655 builder.create_vector(&items)
656}
657
658fn decode_abi_params(
659 params: Option<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<fb::AbiParam<'_>>>>,
660) -> Result<Vec<AbiParam>, ProtocolError> {
661 let mut out = Vec::new();
662 if let Some(vec) = params {
663 for param in vec {
664 out.push(decode_abi_param(param)?);
665 }
666 }
667 Ok(out)
668}
669
670fn encode_abi_param<'bldr>(
671 builder: &mut FlatBufferBuilder<'bldr>,
672 param: &AbiParam,
673) -> flatbuffers::WIPOffset<fb::AbiParam<'bldr>> {
674 let (kind, scalar_type) = match param {
675 AbiParam::Scalar(scalar) => (fb::AbiParamKind::Scalar, encode_abi_scalar_type(*scalar)),
676 AbiParam::Buffer => (fb::AbiParamKind::Buffer, fb::AbiScalarType::I8),
677 };
678
679 fb::AbiParam::create(builder, &fb::AbiParamArgs { kind, scalar_type })
680}
681
682fn decode_abi_param(param: fb::AbiParam<'_>) -> Result<AbiParam, ProtocolError> {
683 match param.kind() {
684 fb::AbiParamKind::Scalar => {
685 let scalar = decode_abi_scalar_type(param.scalar_type())?;
686 Ok(AbiParam::Scalar(scalar))
687 }
688 fb::AbiParamKind::Buffer => Ok(AbiParam::Buffer),
689 _ => Err(ProtocolError::UnknownAbiParamKind),
690 }
691}
692
693fn encode_entrypoint_args<'bldr>(
694 builder: &mut FlatBufferBuilder<'bldr>,
695 args: &[EntrypointArg],
696) -> flatbuffers::WIPOffset<
697 flatbuffers::Vector<'bldr, flatbuffers::ForwardsUOffset<fb::EntrypointArg<'bldr>>>,
698> {
699 let items: Vec<_> = args
700 .iter()
701 .map(|arg| encode_entrypoint_arg(builder, arg))
702 .collect();
703 builder.create_vector(&items)
704}
705
706fn decode_entrypoint_args(
707 args: Option<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<fb::EntrypointArg<'_>>>>,
708) -> Result<Vec<EntrypointArg>, ProtocolError> {
709 let mut out = Vec::new();
710 if let Some(vec) = args {
711 for arg in vec {
712 out.push(decode_entrypoint_arg(arg)?);
713 }
714 }
715 Ok(out)
716}
717
718fn encode_entrypoint_arg<'bldr>(
719 builder: &mut FlatBufferBuilder<'bldr>,
720 arg: &EntrypointArg,
721) -> flatbuffers::WIPOffset<fb::EntrypointArg<'bldr>> {
722 match arg {
723 EntrypointArg::Scalar(value) => {
724 let scalar = encode_scalar_value(builder, value);
725 fb::EntrypointArg::create(
726 builder,
727 &fb::EntrypointArgArgs {
728 kind: fb::EntrypointArgKind::Scalar,
729 scalar: Some(scalar),
730 buffer: None,
731 resource: 0,
732 },
733 )
734 }
735 EntrypointArg::Buffer(bytes) => {
736 let buffer = builder.create_vector(bytes);
737 fb::EntrypointArg::create(
738 builder,
739 &fb::EntrypointArgArgs {
740 kind: fb::EntrypointArgKind::Buffer,
741 scalar: None,
742 buffer: Some(buffer),
743 resource: 0,
744 },
745 )
746 }
747 EntrypointArg::Resource(handle) => fb::EntrypointArg::create(
748 builder,
749 &fb::EntrypointArgArgs {
750 kind: fb::EntrypointArgKind::Resource,
751 scalar: None,
752 buffer: None,
753 resource: *handle,
754 },
755 ),
756 }
757}
758
759fn decode_entrypoint_arg(arg: fb::EntrypointArg<'_>) -> Result<EntrypointArg, ProtocolError> {
760 match arg.kind() {
761 fb::EntrypointArgKind::Scalar => {
762 let scalar = arg
763 .scalar()
764 .ok_or(ProtocolError::MissingField("entrypoint_arg.scalar"))?;
765 Ok(EntrypointArg::Scalar(decode_scalar_value(scalar)?))
766 }
767 fb::EntrypointArgKind::Buffer => {
768 let payload = arg
769 .buffer()
770 .map(|buf| buf.iter().collect())
771 .unwrap_or_default();
772 Ok(EntrypointArg::Buffer(payload))
773 }
774 fb::EntrypointArgKind::Resource => Ok(EntrypointArg::Resource(arg.resource())),
775 _ => Err(ProtocolError::UnknownEntrypointArgKind),
776 }
777}
778
779fn encode_scalar_value<'bldr>(
780 builder: &mut FlatBufferBuilder<'bldr>,
781 value: &AbiScalarValue,
782) -> flatbuffers::WIPOffset<fb::ScalarValue<'bldr>> {
783 let (kind, bits) = scalar_bits(value);
784 fb::ScalarValue::create(builder, &fb::ScalarValueArgs { kind, bits })
785}
786
787fn decode_scalar_value(value: fb::ScalarValue<'_>) -> Result<AbiScalarValue, ProtocolError> {
788 let kind = decode_abi_scalar_type(value.kind())?;
789 let bits = value.bits();
790 let bytes = bits.to_le_bytes();
791 let scalar = match kind {
792 AbiScalarType::I8 => AbiScalarValue::I8(i8::from_le_bytes([bytes[0]])),
793 AbiScalarType::U8 => AbiScalarValue::U8(bytes[0]),
794 AbiScalarType::I16 => AbiScalarValue::I16(i16::from_le_bytes([bytes[0], bytes[1]])),
795 AbiScalarType::U16 => AbiScalarValue::U16(u16::from_le_bytes([bytes[0], bytes[1]])),
796 AbiScalarType::I32 => {
797 AbiScalarValue::I32(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
798 }
799 AbiScalarType::U32 => {
800 AbiScalarValue::U32(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
801 }
802 AbiScalarType::I64 => AbiScalarValue::I64(i64::from_le_bytes(bytes)),
803 AbiScalarType::U64 => AbiScalarValue::U64(bits),
804 AbiScalarType::F32 => AbiScalarValue::F32(f32::from_bits(u32::from_le_bytes([
805 bytes[0], bytes[1], bytes[2], bytes[3],
806 ]))),
807 AbiScalarType::F64 => AbiScalarValue::F64(f64::from_bits(bits)),
808 };
809 Ok(scalar)
810}
811
812fn scalar_bits(value: &AbiScalarValue) -> (fb::AbiScalarType, u64) {
813 match value {
814 AbiScalarValue::I8(v) => (
815 fb::AbiScalarType::I8,
816 u64::from_le_bytes(i64::from(*v).to_le_bytes()),
817 ),
818 AbiScalarValue::U8(v) => (fb::AbiScalarType::U8, u64::from(*v)),
819 AbiScalarValue::I16(v) => (
820 fb::AbiScalarType::I16,
821 u64::from_le_bytes(i64::from(*v).to_le_bytes()),
822 ),
823 AbiScalarValue::U16(v) => (fb::AbiScalarType::U16, u64::from(*v)),
824 AbiScalarValue::I32(v) => (
825 fb::AbiScalarType::I32,
826 u64::from_le_bytes(i64::from(*v).to_le_bytes()),
827 ),
828 AbiScalarValue::U32(v) => (fb::AbiScalarType::U32, u64::from(*v)),
829 AbiScalarValue::I64(v) => (fb::AbiScalarType::I64, u64::from_le_bytes(v.to_le_bytes())),
830 AbiScalarValue::U64(v) => (fb::AbiScalarType::U64, *v),
831 AbiScalarValue::F32(v) => (fb::AbiScalarType::F32, u64::from(v.to_bits())),
832 AbiScalarValue::F64(v) => (fb::AbiScalarType::F64, v.to_bits()),
833 }
834}
835
836fn encode_abi_scalar_type(value: AbiScalarType) -> fb::AbiScalarType {
837 match value {
838 AbiScalarType::I8 => fb::AbiScalarType::I8,
839 AbiScalarType::U8 => fb::AbiScalarType::U8,
840 AbiScalarType::I16 => fb::AbiScalarType::I16,
841 AbiScalarType::U16 => fb::AbiScalarType::U16,
842 AbiScalarType::I32 => fb::AbiScalarType::I32,
843 AbiScalarType::U32 => fb::AbiScalarType::U32,
844 AbiScalarType::I64 => fb::AbiScalarType::I64,
845 AbiScalarType::U64 => fb::AbiScalarType::U64,
846 AbiScalarType::F32 => fb::AbiScalarType::F32,
847 AbiScalarType::F64 => fb::AbiScalarType::F64,
848 }
849}
850
851fn decode_abi_scalar_type(value: fb::AbiScalarType) -> Result<AbiScalarType, ProtocolError> {
852 match value {
853 fb::AbiScalarType::I8 => Ok(AbiScalarType::I8),
854 fb::AbiScalarType::U8 => Ok(AbiScalarType::U8),
855 fb::AbiScalarType::I16 => Ok(AbiScalarType::I16),
856 fb::AbiScalarType::U16 => Ok(AbiScalarType::U16),
857 fb::AbiScalarType::I32 => Ok(AbiScalarType::I32),
858 fb::AbiScalarType::U32 => Ok(AbiScalarType::U32),
859 fb::AbiScalarType::I64 => Ok(AbiScalarType::I64),
860 fb::AbiScalarType::U64 => Ok(AbiScalarType::U64),
861 fb::AbiScalarType::F32 => Ok(AbiScalarType::F32),
862 fb::AbiScalarType::F64 => Ok(AbiScalarType::F64),
863 _ => Err(ProtocolError::UnknownAbiScalarType),
864 }
865}
866
867fn encode_io_frame<'bldr>(
868 builder: &mut FlatBufferBuilder<'bldr>,
869 frame: &IoFrame,
870) -> flatbuffers::WIPOffset<fb::IoFrame<'bldr>> {
871 let payload = builder.create_vector(&frame.payload);
872 fb::IoFrame::create(
873 builder,
874 &fb::IoFrameArgs {
875 writer_id: frame.writer_id,
876 payload: Some(payload),
877 },
878 )
879}
880
881fn decode_io_frame(frame: fb::IoFrame<'_>) -> Result<IoFrame, ProtocolError> {
882 let payload = frame
883 .payload()
884 .map(|buf| buf.iter().collect())
885 .unwrap_or_default();
886 Ok(IoFrame {
887 writer_id: frame.writer_id(),
888 payload,
889 })
890}