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 status: None,
562 }
563 };
564
565 let timestamp = |ts: $crate::guest::dynclib_abi::TimestampV1| {
566 std::time::UNIX_EPOCH
567 + std::time::Duration::new(ts.seconds, ts.nanoseconds)
568 };
569
570 match payload.hook {
571 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_CONNECTING => {
572 __actr_poll_unit!(workload.on_signaling_connecting(Some(&ctx)));
573 }
574 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_CONNECTED => {
575 __actr_poll_unit!(workload.on_signaling_connected(Some(&ctx)));
576 }
577 $crate::guest::dynclib_abi::runtime_hook::ON_SIGNALING_DISCONNECTED => {
578 __actr_poll_unit!(workload.on_signaling_disconnected(&ctx));
579 }
580 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_CONNECTING => {
581 let event = match payload.peer {
582 Some(peer) => peer_event(peer),
583 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
584 };
585 __actr_poll_unit!(workload.on_websocket_connecting(&ctx, &event));
586 }
587 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_CONNECTED => {
588 let event = match payload.peer {
589 Some(peer) => peer_event(peer),
590 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
591 };
592 __actr_poll_unit!(workload.on_websocket_connected(&ctx, &event));
593 }
594 $crate::guest::dynclib_abi::runtime_hook::ON_WEBSOCKET_DISCONNECTED => {
595 let event = match payload.peer {
596 Some(peer) => peer_event(peer),
597 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
598 };
599 __actr_poll_unit!(workload.on_websocket_disconnected(&ctx, &event));
600 }
601 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_CONNECTING => {
602 let event = match payload.peer {
603 Some(peer) => peer_event(peer),
604 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
605 };
606 __actr_poll_unit!(workload.on_webrtc_connecting(&ctx, &event));
607 }
608 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_CONNECTED => {
609 let event = match payload.peer {
610 Some(peer) => peer_event(peer),
611 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
612 };
613 __actr_poll_unit!(workload.on_webrtc_connected(&ctx, &event));
614 }
615 $crate::guest::dynclib_abi::runtime_hook::ON_WEBRTC_DISCONNECTED => {
616 let event = match payload.peer {
617 Some(peer) => peer_event(peer),
618 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
619 };
620 __actr_poll_unit!(workload.on_webrtc_disconnected(&ctx, &event));
621 }
622 $crate::guest::dynclib_abi::runtime_hook::ON_CREDENTIAL_RENEWED => {
623 let event = match payload.credential {
624 Some(credential) => $crate::CredentialEvent {
625 new_expiry: timestamp(credential.new_expiry),
626 },
627 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
628 };
629 __actr_poll_unit!(workload.on_credential_renewed(&ctx, &event));
630 }
631 $crate::guest::dynclib_abi::runtime_hook::ON_CREDENTIAL_EXPIRING => {
632 let event = match payload.credential {
633 Some(credential) => $crate::CredentialEvent {
634 new_expiry: timestamp(credential.new_expiry),
635 },
636 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
637 };
638 __actr_poll_unit!(workload.on_credential_expiring(&ctx, &event));
639 }
640 $crate::guest::dynclib_abi::runtime_hook::ON_MAILBOX_BACKPRESSURE => {
641 let event = match payload.backpressure {
642 Some(backpressure) => $crate::BackpressureEvent {
643 queue_len: backpressure.queue_len as usize,
644 threshold: backpressure.threshold as usize,
645 },
646 None => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
647 };
648 __actr_poll_unit!(workload.on_mailbox_backpressure(&ctx, &event));
649 }
650 _ => return $crate::guest::dynclib_abi::code::UNSUPPORTED_OP,
651 }
652
653 let resp_bytes = match $crate::guest::dynclib_abi::success_reply(::std::vec::Vec::new()) {
654 Ok(bytes) => bytes,
655 Err(code) => return code,
656 };
657
658 let resp_len = resp_bytes.len();
659 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
660 Ok(l) => l,
661 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
662 };
663 let ptr = unsafe { std::alloc::alloc(layout) };
664 if ptr.is_null() {
665 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
666 }
667
668 unsafe {
669 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
670 *resp_out = ptr;
671 *resp_len_out = resp_len;
672 }
673
674 return $crate::guest::dynclib_abi::code::SUCCESS;
675 }
676
677 if frame.op == $crate::guest::dynclib_abi::op::GUEST_DATA_STREAM {
678 let payload = match <$crate::guest::dynclib_abi::GuestDataStreamV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
679 Ok(payload) => payload,
680 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
681 };
682
683 let resp_bytes = match $crate::guest::dynclib::context::dispatch_registered_stream(payload) {
684 Ok(()) => match $crate::guest::dynclib_abi::success_reply(::std::vec::Vec::new()) {
685 Ok(bytes) => bytes,
686 Err(code) => return code,
687 },
688 Err(err) => match $crate::guest::dynclib_abi::error_reply(
689 $crate::guest::dynclib_abi::code::HANDLE_FAILED,
690 err.to_string().into_bytes(),
691 ) {
692 Ok(bytes) => bytes,
693 Err(code) => return code,
694 },
695 };
696
697 let resp_len = resp_bytes.len();
698 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
699 Ok(l) => l,
700 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
701 };
702 let ptr = unsafe { std::alloc::alloc(layout) };
703 if ptr.is_null() {
704 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
705 }
706
707 unsafe {
708 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
709 *resp_out = ptr;
710 *resp_len_out = resp_len;
711 }
712
713 return $crate::guest::dynclib_abi::code::SUCCESS;
714 }
715
716 if frame.op != $crate::guest::dynclib_abi::op::GUEST_HANDLE {
717 return $crate::guest::dynclib_abi::code::UNSUPPORTED_OP;
718 }
719
720 let handle = match <$crate::guest::dynclib_abi::GuestHandleV1 as $crate::guest::dynclib_abi::AbiPayload>::decode_payload(&frame.payload) {
721 Ok(handle) => handle,
722 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
723 };
724
725 let envelope = match actr_protocol::RpcEnvelope::decode(handle.rpc_envelope.as_slice()) {
726 Ok(e) => e,
727 Err(_) => return $crate::guest::dynclib_abi::code::PROTOCOL_ERROR,
728 };
729
730 let ctx = match unsafe {
731 $crate::guest::dynclib::context::DynclibContext::from_invocation(vtable, handle.ctx)
732 } {
733 Ok(c) => c,
734 Err(_) => return $crate::guest::dynclib_abi::code::HANDLE_FAILED,
735 };
736
737 let workload = unsafe {
739 match __ACTR_WORKLOAD.as_ref() {
740 Some(w) => w,
741 None => return $crate::guest::dynclib_abi::code::INIT_FAILED,
742 }
743 };
744
745 type Dispatcher = <$workload_type as Workload>::Dispatcher;
747
748 let resp_result = {
753 let fut = Dispatcher::dispatch(workload, envelope, &ctx);
754 let waker = std::task::Waker::noop();
755 let mut cx = std::task::Context::from_waker(waker);
756 let mut pinned = std::pin::pin!(fut);
757 match pinned.as_mut().poll(&mut cx) {
758 std::task::Poll::Ready(v) => v,
759 std::task::Poll::Pending => {
760 return $crate::guest::dynclib_abi::code::HANDLE_FAILED;
761 }
762 }
763 };
764
765 let resp_bytes = match resp_result {
766 Ok(b) => match $crate::guest::dynclib_abi::success_reply(b.to_vec()) {
767 Ok(bytes) => bytes,
768 Err(code) => return code,
769 },
770 Err(err) => match $crate::guest::dynclib_abi::error_reply(
771 $crate::guest::dynclib_abi::code::HANDLE_FAILED,
772 err.to_string().into_bytes(),
773 ) {
774 Ok(bytes) => bytes,
775 Err(code) => return code,
776 },
777 };
778
779 let resp_len = resp_bytes.len();
781 let layout = match std::alloc::Layout::from_size_align(resp_len.max(1), 1) {
782 Ok(l) => l,
783 Err(_) => return $crate::guest::dynclib_abi::code::GENERIC_ERROR,
784 };
785 let ptr = unsafe { std::alloc::alloc(layout) };
786 if ptr.is_null() {
787 return $crate::guest::dynclib_abi::code::GENERIC_ERROR;
788 }
789
790 unsafe {
791 std::ptr::copy_nonoverlapping(resp_bytes.as_ptr(), ptr, resp_len);
792 *resp_out = ptr;
793 *resp_len_out = resp_len;
794 }
795
796 $crate::guest::dynclib_abi::code::SUCCESS
797 }
798
799 #[unsafe(no_mangle)]
803 pub unsafe extern "C" fn actr_free_response(ptr: *mut u8, len: usize) {
804 if ptr.is_null() || len == 0 {
805 return;
806 }
807 let layout = match std::alloc::Layout::from_size_align(len, 1) {
808 Ok(l) => l,
809 Err(_) => return,
810 };
811 unsafe { std::alloc::dealloc(ptr, layout) };
812 }
813 };
814 };
815}