1pub mod dynclib_abi;
36pub mod vtable;
37
38#[cfg(all(target_arch = "wasm32", not(feature = "web")))]
43pub mod wasm;
44
45#[cfg(feature = "cdylib")]
46pub mod dynclib;
47
48#[cfg(all(target_arch = "wasm32", not(feature = "web")))]
52#[doc(hidden)]
53pub mod __wasm_macro_support {
54 pub use super::wasm::adapter::{
60 WorkloadCell, run_dispatch, run_on_credential_expiring, run_on_credential_renewed,
61 run_on_data_stream, run_on_error, run_on_mailbox_backpressure, run_on_ready,
62 run_on_signaling_connected, run_on_signaling_connecting, run_on_signaling_disconnected,
63 run_on_start, run_on_stop, run_on_webrtc_connected, run_on_webrtc_connecting,
64 run_on_webrtc_disconnected, run_on_websocket_connected, run_on_websocket_connecting,
65 run_on_websocket_disconnected,
66 };
67 pub use super::wasm::generated::actr::workload::types::{
68 ActrError as WitActrError, ActrId as WitActrId, BackpressureEvent as WitBackpressureEvent,
69 CredentialEvent as WitCredentialEvent, DataStream as WitDataStream,
70 ErrorEvent as WitErrorEvent, PeerEvent as WitPeerEvent, RpcEnvelope as WitRpcEnvelope,
71 };
72 pub use super::wasm::generated::exports::actr::workload::workload::Guest;
73}
74
75#[macro_export]
116macro_rules! entry {
117 ($workload_type:ty) => {
119 $crate::entry!($workload_type, <$workload_type as ::core::default::Default>::default());
120 };
121
122 ($workload_type:ty, $init_expr:expr) => {
124 #[cfg(all(target_arch = "wasm32", not(feature = "web")))]
135 const _: () = {
136 static __ACTR_WORKLOAD: $crate::guest::__wasm_macro_support::WorkloadCell<$workload_type> =
139 $crate::guest::__wasm_macro_support::WorkloadCell::new();
140
141 fn __actr_workload() -> &'static $workload_type {
142 __ACTR_WORKLOAD.get_or_init(|| -> $workload_type { $init_expr })
143 }
144
145 struct __ActrEntryAdapter;
146
147 impl $crate::guest::__wasm_macro_support::Guest for __ActrEntryAdapter {
148 async fn dispatch(
149 envelope: $crate::guest::__wasm_macro_support::WitRpcEnvelope,
150 ) -> ::core::result::Result<
151 ::std::vec::Vec<u8>,
152 $crate::guest::__wasm_macro_support::WitActrError,
153 > {
154 $crate::guest::__wasm_macro_support::run_dispatch(
155 __actr_workload(),
156 envelope,
157 )
158 .await
159 }
160
161 async fn on_start() -> ::core::result::Result<
162 (),
163 $crate::guest::__wasm_macro_support::WitActrError,
164 > {
165 $crate::guest::__wasm_macro_support::run_on_start(__actr_workload()).await
166 }
167
168 async fn on_ready() -> ::core::result::Result<
169 (),
170 $crate::guest::__wasm_macro_support::WitActrError,
171 > {
172 $crate::guest::__wasm_macro_support::run_on_ready(__actr_workload()).await
173 }
174
175 async fn on_stop() -> ::core::result::Result<
176 (),
177 $crate::guest::__wasm_macro_support::WitActrError,
178 > {
179 $crate::guest::__wasm_macro_support::run_on_stop(__actr_workload()).await
180 }
181
182 async fn on_error(
183 event: $crate::guest::__wasm_macro_support::WitErrorEvent,
184 ) -> ::core::result::Result<
185 (),
186 $crate::guest::__wasm_macro_support::WitActrError,
187 > {
188 $crate::guest::__wasm_macro_support::run_on_error(__actr_workload(), event)
189 .await
190 }
191
192 async fn on_signaling_connecting() {
193 $crate::guest::__wasm_macro_support::run_on_signaling_connecting(
194 __actr_workload(),
195 )
196 .await
197 }
198
199 async fn on_signaling_connected() {
200 $crate::guest::__wasm_macro_support::run_on_signaling_connected(
201 __actr_workload(),
202 )
203 .await
204 }
205
206 async fn on_signaling_disconnected() {
207 $crate::guest::__wasm_macro_support::run_on_signaling_disconnected(
208 __actr_workload(),
209 )
210 .await
211 }
212
213 async fn on_websocket_connecting(
214 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
215 ) {
216 $crate::guest::__wasm_macro_support::run_on_websocket_connecting(
217 __actr_workload(),
218 event,
219 )
220 .await
221 }
222
223 async fn on_websocket_connected(
224 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
225 ) {
226 $crate::guest::__wasm_macro_support::run_on_websocket_connected(
227 __actr_workload(),
228 event,
229 )
230 .await
231 }
232
233 async fn on_websocket_disconnected(
234 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
235 ) {
236 $crate::guest::__wasm_macro_support::run_on_websocket_disconnected(
237 __actr_workload(),
238 event,
239 )
240 .await
241 }
242
243 async fn on_webrtc_connecting(
244 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
245 ) {
246 $crate::guest::__wasm_macro_support::run_on_webrtc_connecting(
247 __actr_workload(),
248 event,
249 )
250 .await
251 }
252
253 async fn on_webrtc_connected(
254 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
255 ) {
256 $crate::guest::__wasm_macro_support::run_on_webrtc_connected(
257 __actr_workload(),
258 event,
259 )
260 .await
261 }
262
263 async fn on_webrtc_disconnected(
264 event: $crate::guest::__wasm_macro_support::WitPeerEvent,
265 ) {
266 $crate::guest::__wasm_macro_support::run_on_webrtc_disconnected(
267 __actr_workload(),
268 event,
269 )
270 .await
271 }
272
273 async fn on_credential_renewed(
274 event: $crate::guest::__wasm_macro_support::WitCredentialEvent,
275 ) {
276 $crate::guest::__wasm_macro_support::run_on_credential_renewed(
277 __actr_workload(),
278 event,
279 )
280 .await
281 }
282
283 async fn on_credential_expiring(
284 event: $crate::guest::__wasm_macro_support::WitCredentialEvent,
285 ) {
286 $crate::guest::__wasm_macro_support::run_on_credential_expiring(
287 __actr_workload(),
288 event,
289 )
290 .await
291 }
292
293 async fn on_mailbox_backpressure(
294 event: $crate::guest::__wasm_macro_support::WitBackpressureEvent,
295 ) {
296 $crate::guest::__wasm_macro_support::run_on_mailbox_backpressure(
297 __actr_workload(),
298 event,
299 )
300 .await
301 }
302
303 async fn on_data_stream(
304 chunk: $crate::guest::__wasm_macro_support::WitDataStream,
305 sender: $crate::guest::__wasm_macro_support::WitActrId,
306 ) -> ::core::result::Result<
307 (),
308 $crate::guest::__wasm_macro_support::WitActrError,
309 > {
310 $crate::guest::__wasm_macro_support::run_on_data_stream(chunk, sender).await
311 }
312 }
313
314 $crate::guest::wasm::generated::export!(__ActrEntryAdapter with_types_in $crate::guest::wasm::generated);
315 };
316
317 #[cfg(all(target_arch = "wasm32", feature = "web"))]
327 const _: () = {
328 #[$crate::web::__web_macro_support::wasm_bindgen(start)]
338 fn __actr_web_bootstrap() {
339 let workload: $workload_type = $init_expr;
340 let adapter =
341 $crate::web::__web_macro_support::WebWorkloadAdapter::new(workload);
342 $crate::web::__web_macro_support::register_workload(adapter);
343 }
344 };
345
346 #[cfg(feature = "cdylib")]
351 const _: () = {
352 static mut __ACTR_WORKLOAD: Option<$workload_type> = None;
353 static mut __ACTR_VTABLE: Option<*const $crate::guest::vtable::HostVTable> = None;
354
355 #[unsafe(no_mangle)]
361 pub unsafe extern "C" fn actr_init(
362 vtable: *const $crate::guest::vtable::HostVTable,
363 init_ptr: *const u8,
364 init_len: usize,
365 ) -> i32 {
366 if vtable.is_null() {
367 return $crate::guest::dynclib_abi::code::INIT_FAILED;
368 }
369
370 let init_bytes = if init_ptr.is_null() || init_len == 0 {
371 &[][..]
372 } else {
373 unsafe { std::slice::from_raw_parts(init_ptr, init_len) }
374 };
375
376 if $crate::guest::dynclib_abi::decode_message::<$crate::guest::dynclib_abi::InitPayloadV1>(
381 init_bytes,
382 )
383 .is_err()
384 {
385 return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR;
386 }
387
388 let workload: $workload_type = $init_expr;
389 unsafe {
390 if __ACTR_WORKLOAD.is_some() {
391 return $crate::guest::dynclib_abi::code::INIT_FAILED;
392 }
393 __ACTR_VTABLE = Some(vtable);
394 __ACTR_WORKLOAD = Some(workload);
395 }
396 $crate::guest::dynclib_abi::code::SUCCESS
397 }
398
399 #[unsafe(no_mangle)]
401 pub unsafe extern "C" fn actr_handle(
402 req_ptr: *const u8,
403 req_len: usize,
404 resp_out: *mut *mut u8,
405 resp_len_out: *mut usize,
406 ) -> i32 {
407 use actr_protocol::prost::Message as ProstMessage;
408 use $crate::{MessageDispatcher, Workload};
409
410 let vtable = match unsafe { __ACTR_VTABLE } {
412 Some(vt) => vt,
413 None => return $crate::guest::dynclib_abi::code::INIT_FAILED,
414 };
415
416 if req_ptr.is_null() {
418 return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR;
419 }
420 let req_bytes = unsafe { std::slice::from_raw_parts(req_ptr, req_len) };
421
422 let frame = match $crate::guest::dynclib_abi::decode_message::<
423 $crate::guest::dynclib_abi::AbiFrame,
424 >(req_bytes) {
425 Ok(f) => f,
426 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
427 };
428
429 if frame.op == $crate::guest::dynclib_abi::op::GUEST_LIFECYCLE {
430 let payload = match <$crate::guest::dynclib_abi::GuestLifecycleV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
431 Ok(payload) => payload,
432 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
433 };
434
435 let ctx = match unsafe {
436 $crate::guest::dynclib::context::DynclibContext::from_invocation(vtable, payload.ctx)
437 } {
438 Ok(c) => c,
439 Err(_) => return $crate::guest::dynclib_abi::code::HANDLE_FAILED,
440 };
441
442 let workload = unsafe {
443 match __ACTR_WORKLOAD.as_ref() {
444 Some(w) => w,
445 None => return $crate::guest::dynclib_abi::code::INIT_FAILED,
446 }
447 };
448
449 let lifecycle_result = match payload.hook {
450 $crate::guest::dynclib_abi::lifecycle_hook::ON_START => {
451 let fut = workload.on_start(&ctx);
452 let waker = std::task::Waker::noop();
453 let mut cx = std::task::Context::from_waker(waker);
454 let mut pinned = std::pin::pin!(fut);
455 match pinned.as_mut().poll(&mut cx) {
456 std::task::Poll::Ready(v) => v,
457 std::task::Poll::Pending => {
458 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
459 }
460 }
461 }
462 $crate::guest::dynclib_abi::lifecycle_hook::ON_READY => {
463 let fut = workload.on_ready(&ctx);
464 let waker = std::task::Waker::noop();
465 let mut cx = std::task::Context::from_waker(waker);
466 let mut pinned = std::pin::pin!(fut);
467 match pinned.as_mut().poll(&mut cx) {
468 std::task::Poll::Ready(v) => v,
469 std::task::Poll::Pending => {
470 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
471 }
472 }
473 }
474 $crate::guest::dynclib_abi::lifecycle_hook::ON_STOP => {
475 let fut = workload.on_stop(&ctx);
476 let waker = std::task::Waker::noop();
477 let mut cx = std::task::Context::from_waker(waker);
478 let mut pinned = std::pin::pin!(fut);
479 match pinned.as_mut().poll(&mut cx) {
480 std::task::Poll::Ready(v) => v,
481 std::task::Poll::Pending => {
482 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
483 }
484 }
485 }
486 _ => return $crate::guest::dynclib_abi::code::UNSUPPORTED_OP,
487 };
488
489 let resp_bytes = match lifecycle_result {
490 Ok(()) => match $crate::guest::dynclib_abi::success_reply(::std::vec::Vec::new()) {
491 Ok(bytes) => bytes,
492 Err(code) => return code,
493 },
494 Err(err) => match $crate::guest::dynclib_abi::error_reply(
495 $crate::guest::dynclib_abi::code::HANDLE_FAILED,
496 err.to_string().into_bytes(),
497 ) {
498 Ok(bytes) => bytes,
499 Err(code) => return code,
500 },
501 };
502
503 let resp_len = resp_bytes.len();
504 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
505 Ok(l) => l,
506 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
507 };
508 let ptr = unsafe { std::alloc::alloc(layout) };
509 if ptr.is_null() {
510 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
511 }
512
513 unsafe {
514 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
515 *resp_out = ptr;
516 *resp_len_out = resp_len;
517 }
518
519 return $crate::guest::dynclib_abi::code::SUCCESS;
520 }
521
522 if frame.op == $crate::guest::dynclib_abi::op::GUEST_HOOK {
523 let payload = match <$crate::guest::dynclib_abi::GuestHookV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
524 Ok(payload) => payload,
525 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
526 };
527
528 let ctx = match unsafe {
529 $crate::guest::dynclib::context::DynclibContext::from_invocation(vtable, payload.ctx)
530 } {
531 Ok(c) => c,
532 Err(_) => return $crate::guest::dynclib_abi::code::HANDLE_FAILED,
533 };
534
535 let workload = unsafe {
536 match __ACTR_WORKLOAD.as_ref() {
537 Some(w) => w,
538 None => return $crate::guest::dynclib_abi::code::INIT_FAILED,
539 }
540 };
541
542 macro_rules! __actr_poll_unit {
543 ($future:expr) => {{
544 let fut = $future;
545 let waker = std::task::Waker::noop();
546 let mut cx = std::task::Context::from_waker(waker);
547 let mut pinned = std::pin::pin!(fut);
548 match pinned.as_mut().poll(&mut cx) {
549 std::task::Poll::Ready(()) => {}
550 std::task::Poll::Pending => {
551 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
552 }
553 }
554 }};
555 }
556
557 let peer_event = |peer: $crate::guest::dynclib_abi::PeerEventV1| {
558 $crate::PeerEvent {
559 peer: peer.peer,
560 relayed: peer.relayed,
561 }
562 };
563
564 let timestamp = |ts: $crate::guest::dynclib_abi::TimestampV1| {
565 std::time::UNIX_EPOCH
566 + std::time::Duration::new(ts.seconds, ts.nanoseconds)
567 };
568
569 match payload.hook {
570 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_CONNECTING => {
571 __actr_poll_unit!(workload.on_signaling_connecting(Some(&ctx)));
572 }
573 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_CONNECTED => {
574 __actr_poll_unit!(workload.on_signaling_connected(Some(&ctx)));
575 }
576 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_DISCONNECTED => {
577 __actr_poll_unit!(workload.on_signaling_disconnected(&ctx));
578 }
579 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_CONNECTING => {
580 let event = match payload.peer {
581 Some(peer) => peer_event(peer),
582 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
583 };
584 __actr_poll_unit!(workload.on_websocket_connecting(&ctx, &event));
585 }
586 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_CONNECTED => {
587 let event = match payload.peer {
588 Some(peer) => peer_event(peer),
589 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
590 };
591 __actr_poll_unit!(workload.on_websocket_connected(&ctx, &event));
592 }
593 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_DISCONNECTED => {
594 let event = match payload.peer {
595 Some(peer) => peer_event(peer),
596 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
597 };
598 __actr_poll_unit!(workload.on_websocket_disconnected(&ctx, &event));
599 }
600 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_CONNECTING => {
601 let event = match payload.peer {
602 Some(peer) => peer_event(peer),
603 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
604 };
605 __actr_poll_unit!(workload.on_webrtc_connecting(&ctx, &event));
606 }
607 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_CONNECTED => {
608 let event = match payload.peer {
609 Some(peer) => peer_event(peer),
610 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
611 };
612 __actr_poll_unit!(workload.on_webrtc_connected(&ctx, &event));
613 }
614 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_DISCONNECTED => {
615 let event = match payload.peer {
616 Some(peer) => peer_event(peer),
617 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
618 };
619 __actr_poll_unit!(workload.on_webrtc_disconnected(&ctx, &event));
620 }
621 $crate::guest::dynclib_abi::runtime_hook::ON_CREDENTIAL_RENEWED => {
622 let event = match payload.credential {
623 Some(credential) => $crate::CredentialEvent {
624 new_expiry: timestamp(credential.new_expiry),
625 },
626 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
627 };
628 __actr_poll_unit!(workload.on_credential_renewed(&ctx, &event));
629 }
630 $crate::guest::dynclib_abi::runtime_hook::ON_CREDENTIAL_EXPIRING => {
631 let event = match payload.credential {
632 Some(credential) => $crate::CredentialEvent {
633 new_expiry: timestamp(credential.new_expiry),
634 },
635 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
636 };
637 __actr_poll_unit!(workload.on_credential_expiring(&ctx, &event));
638 }
639 $crate::guest::dynclib_abi::runtime_hook::ON_MAILBOX_BACKPRESSURE => {
640 let event = match payload.backpressure {
641 Some(backpressure) => $crate::BackpressureEvent {
642 queue_len: backpressure.queue_len as usize,
643 threshold: backpressure.threshold as usize,
644 },
645 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
646 };
647 __actr_poll_unit!(workload.on_mailbox_backpressure(&ctx, &event));
648 }
649 _ => return $crate::guest::dynclib_abi::code::UNSUPPORTED_OP,
650 }
651
652 let resp_bytes = match $crate::guest::dynclib_abi::success_reply(::std::vec::Vec::new()) {
653 Ok(bytes) => bytes,
654 Err(code) => return code,
655 };
656
657 let resp_len = resp_bytes.len();
658 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
659 Ok(l) => l,
660 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
661 };
662 let ptr = unsafe { std::alloc::alloc(layout) };
663 if ptr.is_null() {
664 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
665 }
666
667 unsafe {
668 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
669 *resp_out = ptr;
670 *resp_len_out = resp_len;
671 }
672
673 return $crate::guest::dynclib_abi::code::SUCCESS;
674 }
675
676 if frame.op == $crate::guest::dynclib_abi::op::GUEST_DATA_STREAM {
677 let payload = match <$crate::guest::dynclib_abi::GuestDataStreamV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
678 Ok(payload) => payload,
679 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
680 };
681
682 let resp_bytes = match $crate::guest::dynclib::context::dispatch_registered_stream(payload) {
683 Ok(()) => match $crate::guest::dynclib_abi::success_reply(::std::vec::Vec::new()) {
684 Ok(bytes) => bytes,
685 Err(code) => return code,
686 },
687 Err(err) => match $crate::guest::dynclib_abi::error_reply(
688 $crate::guest::dynclib_abi::code::HANDLE_FAILED,
689 err.to_string().into_bytes(),
690 ) {
691 Ok(bytes) => bytes,
692 Err(code) => return code,
693 },
694 };
695
696 let resp_len = resp_bytes.len();
697 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
698 Ok(l) => l,
699 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
700 };
701 let ptr = unsafe { std::alloc::alloc(layout) };
702 if ptr.is_null() {
703 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
704 }
705
706 unsafe {
707 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
708 *resp_out = ptr;
709 *resp_len_out = resp_len;
710 }
711
712 return $crate::guest::dynclib_abi::code::SUCCESS;
713 }
714
715 if frame.op != $crate::guest::dynclib_abi::op::GUEST_HANDLE {
716 return $crate::guest::dynclib_abi::code::UNSUPPORTED_OP;
717 }
718
719 let handle = match <$crate::guest::dynclib_abi::GuestHandleV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
720 Ok(handle) => handle,
721 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
722 };
723
724 let envelope = match actr_protocol::RpcEnvelope::decode(handle.rpc_envelope.as_slice()) {
725 Ok(e) => e,
726 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
727 };
728
729 let ctx = match unsafe {
730 $crate::guest::dynclib::context::DynclibContext::from_invocation(vtable, handle.ctx)
731 } {
732 Ok(c) => c,
733 Err(_) => return $crate::guest::dynclib_abi::code::HANDLE_FAILED,
734 };
735
736 let workload = unsafe {
738 match __ACTR_WORKLOAD.as_ref() {
739 Some(w) => w,
740 None => return $crate::guest::dynclib_abi::code::INIT_FAILED,
741 }
742 };
743
744 type Dispatcher = <$workload_type as Workload>::Dispatcher;
746
747 let resp_result = {
752 let fut = Dispatcher::dispatch(workload, envelope, &ctx);
753 let waker = std::task::Waker::noop();
754 let mut cx = std::task::Context::from_waker(waker);
755 let mut pinned = std::pin::pin!(fut);
756 match pinned.as_mut().poll(&mut cx) {
757 std::task::Poll::Ready(v) => v,
758 std::task::Poll::Pending => {
759 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
760 }
761 }
762 };
763
764 let resp_bytes = match resp_result {
765 Ok(b) => match $crate::guest::dynclib_abi::success_reply(b.to_vec()) {
766 Ok(bytes) => bytes,
767 Err(code) => return code,
768 },
769 Err(err) => match $crate::guest::dynclib_abi::error_reply(
770 $crate::guest::dynclib_abi::code::HANDLE_FAILED,
771 err.to_string().into_bytes(),
772 ) {
773 Ok(bytes) => bytes,
774 Err(code) => return code,
775 },
776 };
777
778 let resp_len = resp_bytes.len();
780 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
781 Ok(l) => l,
782 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
783 };
784 let ptr = unsafe { std::alloc::alloc(layout) };
785 if ptr.is_null() {
786 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
787 }
788
789 unsafe {
790 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
791 *resp_out = ptr;
792 *resp_len_out = resp_len;
793 }
794
795 $crate::guest::dynclib_abi::code::SUCCESS
796 }
797
798 #[unsafe(no_mangle)]
802 pub unsafe extern "C" fn actr_free_response(ptr: *mut u8, len: usize) {
803 if ptr.is_null() || len == 0 {
804 return;
805 }
806 let layout = match std::alloc::Layout::from_size_align(len, 1) {
807 Ok(l) => l,
808 Err(_) => return,
809 };
810 unsafe { std::alloc::dealloc(ptr, layout) };
811 }
812 };
813 };
814}