1extern crate alloc;
30
31use crate::error::{FabricError, Result};
32use alloc::vec::Vec;
33
34pub const LEASE_STATUS_ACTIVE: u8 = 0;
36pub const LEASE_STATUS_EXPIRED: u8 = 1;
38pub const LEASE_STATUS_REVOKED: u8 = 2;
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub struct FbmuLeaseInfo {
44 pub lease_id: u128,
45 pub expires_at_unix_secs: u64,
46 pub arena_size: u64,
47 pub status: u8,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct FbbuLeaseInfo {
53 pub lease_id: u128,
54 pub expires_at_unix_secs: u64,
55 pub num_blocks: u64,
56 pub block_size: u32,
57 pub status: u8,
58}
59
60#[cfg(target_arch = "wasm32")]
61fn split_u128_words(value: u128) -> (i64, i64) {
62 let hi = (value >> 64) as u64;
63 let lo = value as u64;
64 (hi as i64, lo as i64)
65}
66
67#[cfg(target_arch = "wasm32")]
68fn join_u128_words(hi: i64, lo: i64) -> u128 {
69 ((hi as u64 as u128) << 64) | (lo as u64 as u128)
70}
71
72#[cfg(target_arch = "wasm32")]
77mod wasm {
78 #[link(wasm_import_module = "fabricbios_fbmu_v0")]
79 extern "C" {
80 pub fn fbmu_hello() -> i32;
81 pub fn fbmu_write(offset: i64, ptr: i32, len: i32) -> i32;
82 pub fn fbmu_read(offset: i64, len: i32, out_ptr: i32) -> i32;
83 pub fn fbmu_get_arena_size() -> i64;
84 pub fn fbmu_alloc(
85 min_bytes: i64,
86 lease_secs: i64,
87 lease_hi_ptr: i32,
88 lease_lo_ptr: i32,
89 expires_at_ptr: i32,
90 arena_size_ptr: i32,
91 ) -> i32;
92 pub fn fbmu_query(
93 lease_hi: i64,
94 lease_lo: i64,
95 status_ptr: i32,
96 expires_at_ptr: i32,
97 arena_size_ptr: i32,
98 ) -> i32;
99 pub fn fbmu_renew(
100 lease_hi: i64,
101 lease_lo: i64,
102 duration_secs: i64,
103 expires_at_ptr: i32,
104 ) -> i32;
105 pub fn fbmu_free(lease_hi: i64, lease_lo: i64) -> i32;
106 pub fn fbmu_write_lease(
107 lease_hi: i64,
108 lease_lo: i64,
109 offset: i64,
110 ptr: i32,
111 len: i32,
112 ) -> i32;
113 pub fn fbmu_read_lease(
114 lease_hi: i64,
115 lease_lo: i64,
116 offset: i64,
117 len: i32,
118 out_ptr: i32,
119 ) -> i32;
120 }
121
122 #[link(wasm_import_module = "fabricbios_fbbu_v0")]
123 extern "C" {
124 pub fn fbbu_hello() -> i32;
125 pub fn fbbu_write_block(lba: i64, ptr: i32) -> i32;
126 pub fn fbbu_read_block(lba: i64, out_ptr: i32) -> i32;
127 pub fn fbbu_get_num_blocks() -> i64;
128 pub fn fbbu_alloc(
129 min_blocks: i64,
130 lease_secs: i64,
131 lease_hi_ptr: i32,
132 lease_lo_ptr: i32,
133 expires_at_ptr: i32,
134 num_blocks_ptr: i32,
135 block_size_ptr: i32,
136 ) -> i32;
137 pub fn fbbu_query(
138 lease_hi: i64,
139 lease_lo: i64,
140 status_ptr: i32,
141 expires_at_ptr: i32,
142 num_blocks_ptr: i32,
143 block_size_ptr: i32,
144 ) -> i32;
145 pub fn fbbu_renew(
146 lease_hi: i64,
147 lease_lo: i64,
148 duration_secs: i64,
149 expires_at_ptr: i32,
150 ) -> i32;
151 pub fn fbbu_free(lease_hi: i64, lease_lo: i64) -> i32;
152 pub fn fbbu_write_block_lease(lease_hi: i64, lease_lo: i64, lba: i64, ptr: i32) -> i32;
153 pub fn fbbu_read_block_lease(lease_hi: i64, lease_lo: i64, lba: i64, out_ptr: i32) -> i32;
154 }
155}
156
157#[cfg(target_arch = "wasm32")]
168pub fn fbmu_hello() -> Result<()> {
169 let status = unsafe { wasm::fbmu_hello() };
170 match FabricError::from_status(status) {
171 None => Ok(()),
172 Some(e) => Err(e),
173 }
174}
175
176#[cfg(target_arch = "wasm32")]
182pub fn fbmu_write(offset: u64, data: &[u8]) -> Result<()> {
183 let status =
184 unsafe { wasm::fbmu_write(offset as i64, data.as_ptr() as i32, data.len() as i32) };
185 match FabricError::from_status(status) {
186 None => Ok(()),
187 Some(e) => Err(e),
188 }
189}
190
191#[cfg(target_arch = "wasm32")]
200pub fn fbmu_read(offset: u64, buf: &mut [u8]) -> Result<usize> {
201 let n = unsafe { wasm::fbmu_read(offset as i64, buf.len() as i32, buf.as_mut_ptr() as i32) };
202 if n < 0 {
203 Err(FabricError::from_status(n).unwrap_or(FabricError::IoError(n)))
204 } else {
205 Ok(n as usize)
206 }
207}
208
209#[cfg(target_arch = "wasm32")]
215pub fn fbmu_get_arena_size() -> Result<u64> {
216 let size = unsafe { wasm::fbmu_get_arena_size() };
217 if size < 0 {
218 Err(FabricError::IoError(size as i32))
219 } else {
220 Ok(size as u64)
221 }
222}
223
224#[cfg(target_arch = "wasm32")]
234pub fn fbbu_hello() -> Result<()> {
235 let status = unsafe { wasm::fbbu_hello() };
236 match FabricError::from_status(status) {
237 None => Ok(()),
238 Some(e) => Err(e),
239 }
240}
241
242#[cfg(target_arch = "wasm32")]
249pub fn fbbu_write_block(lba: u64, data: &[u8; 512]) -> Result<()> {
250 let status = unsafe { wasm::fbbu_write_block(lba as i64, data.as_ptr() as i32) };
251 match FabricError::from_status(status) {
252 None => Ok(()),
253 Some(e) => Err(e),
254 }
255}
256
257#[cfg(target_arch = "wasm32")]
264pub fn fbbu_read_block(lba: u64, buf: &mut [u8; 512]) -> Result<()> {
265 let status = unsafe { wasm::fbbu_read_block(lba as i64, buf.as_mut_ptr() as i32) };
266 match FabricError::from_status(status) {
267 None => Ok(()),
268 Some(e) => Err(e),
269 }
270}
271
272#[cfg(target_arch = "wasm32")]
278pub fn fbbu_get_num_blocks() -> Result<u64> {
279 let n = unsafe { wasm::fbbu_get_num_blocks() };
280 if n < 0 {
281 Err(FabricError::IoError(n as i32))
282 } else {
283 Ok(n as u64)
284 }
285}
286
287#[cfg(target_arch = "wasm32")]
289pub fn fbmu_alloc(min_bytes: u64, lease_secs: u64) -> Result<FbmuLeaseInfo> {
290 let mut lease_hi: i64 = 0;
291 let mut lease_lo: i64 = 0;
292 let mut expires_at: i64 = 0;
293 let mut arena_size: i64 = 0;
294 let status = unsafe {
295 wasm::fbmu_alloc(
296 min_bytes as i64,
297 lease_secs as i64,
298 &mut lease_hi as *mut i64 as i32,
299 &mut lease_lo as *mut i64 as i32,
300 &mut expires_at as *mut i64 as i32,
301 &mut arena_size as *mut i64 as i32,
302 )
303 };
304 match FabricError::from_status(status) {
305 None => Ok(FbmuLeaseInfo {
306 lease_id: join_u128_words(lease_hi, lease_lo),
307 expires_at_unix_secs: expires_at as u64,
308 arena_size: arena_size as u64,
309 status: LEASE_STATUS_ACTIVE,
310 }),
311 Some(e) => Err(e),
312 }
313}
314
315#[cfg(target_arch = "wasm32")]
317pub fn fbmu_query(lease_id: u128) -> Result<FbmuLeaseInfo> {
318 let (lease_hi, lease_lo) = split_u128_words(lease_id);
319 let mut lease_status: i32 = LEASE_STATUS_REVOKED as i32;
320 let mut expires_at: i64 = 0;
321 let mut arena_size: i64 = 0;
322 let status = unsafe {
323 wasm::fbmu_query(
324 lease_hi,
325 lease_lo,
326 &mut lease_status as *mut i32 as i32,
327 &mut expires_at as *mut i64 as i32,
328 &mut arena_size as *mut i64 as i32,
329 )
330 };
331 match FabricError::from_status(status) {
332 None => Ok(FbmuLeaseInfo {
333 lease_id,
334 expires_at_unix_secs: expires_at as u64,
335 arena_size: arena_size as u64,
336 status: lease_status as u8,
337 }),
338 Some(e) => Err(e),
339 }
340}
341
342#[cfg(target_arch = "wasm32")]
344pub fn fbmu_renew(lease_id: u128, duration_secs: u64) -> Result<u64> {
345 let (lease_hi, lease_lo) = split_u128_words(lease_id);
346 let mut expires_at: i64 = 0;
347 let status = unsafe {
348 wasm::fbmu_renew(
349 lease_hi,
350 lease_lo,
351 duration_secs as i64,
352 &mut expires_at as *mut i64 as i32,
353 )
354 };
355 match FabricError::from_status(status) {
356 None => Ok(expires_at as u64),
357 Some(e) => Err(e),
358 }
359}
360
361#[cfg(target_arch = "wasm32")]
363pub fn fbmu_free(lease_id: u128) -> Result<()> {
364 let (lease_hi, lease_lo) = split_u128_words(lease_id);
365 let status = unsafe { wasm::fbmu_free(lease_hi, lease_lo) };
366 match FabricError::from_status(status) {
367 None => Ok(()),
368 Some(e) => Err(e),
369 }
370}
371
372#[cfg(target_arch = "wasm32")]
374pub fn fbmu_write_lease(lease_id: u128, offset: u64, data: &[u8]) -> Result<()> {
375 let (lease_hi, lease_lo) = split_u128_words(lease_id);
376 let status = unsafe {
377 wasm::fbmu_write_lease(
378 lease_hi,
379 lease_lo,
380 offset as i64,
381 data.as_ptr() as i32,
382 data.len() as i32,
383 )
384 };
385 match FabricError::from_status(status) {
386 None => Ok(()),
387 Some(e) => Err(e),
388 }
389}
390
391#[cfg(target_arch = "wasm32")]
393pub fn fbmu_read_lease(lease_id: u128, offset: u64, buf: &mut [u8]) -> Result<usize> {
394 let (lease_hi, lease_lo) = split_u128_words(lease_id);
395 let n = unsafe {
396 wasm::fbmu_read_lease(
397 lease_hi,
398 lease_lo,
399 offset as i64,
400 buf.len() as i32,
401 buf.as_mut_ptr() as i32,
402 )
403 };
404 if n < 0 {
405 Err(FabricError::from_status(n).unwrap_or(FabricError::IoError(n)))
406 } else {
407 Ok(n as usize)
408 }
409}
410
411#[cfg(target_arch = "wasm32")]
413pub fn fbbu_alloc(min_blocks: u64, lease_secs: u64) -> Result<FbbuLeaseInfo> {
414 let mut lease_hi: i64 = 0;
415 let mut lease_lo: i64 = 0;
416 let mut expires_at: i64 = 0;
417 let mut num_blocks: i64 = 0;
418 let mut block_size: i32 = 0;
419 let status = unsafe {
420 wasm::fbbu_alloc(
421 min_blocks as i64,
422 lease_secs as i64,
423 &mut lease_hi as *mut i64 as i32,
424 &mut lease_lo as *mut i64 as i32,
425 &mut expires_at as *mut i64 as i32,
426 &mut num_blocks as *mut i64 as i32,
427 &mut block_size as *mut i32 as i32,
428 )
429 };
430 match FabricError::from_status(status) {
431 None => Ok(FbbuLeaseInfo {
432 lease_id: join_u128_words(lease_hi, lease_lo),
433 expires_at_unix_secs: expires_at as u64,
434 num_blocks: num_blocks as u64,
435 block_size: block_size as u32,
436 status: LEASE_STATUS_ACTIVE,
437 }),
438 Some(e) => Err(e),
439 }
440}
441
442#[cfg(target_arch = "wasm32")]
444pub fn fbbu_query(lease_id: u128) -> Result<FbbuLeaseInfo> {
445 let (lease_hi, lease_lo) = split_u128_words(lease_id);
446 let mut lease_status: i32 = LEASE_STATUS_REVOKED as i32;
447 let mut expires_at: i64 = 0;
448 let mut num_blocks: i64 = 0;
449 let mut block_size: i32 = 0;
450 let status = unsafe {
451 wasm::fbbu_query(
452 lease_hi,
453 lease_lo,
454 &mut lease_status as *mut i32 as i32,
455 &mut expires_at as *mut i64 as i32,
456 &mut num_blocks as *mut i64 as i32,
457 &mut block_size as *mut i32 as i32,
458 )
459 };
460 match FabricError::from_status(status) {
461 None => Ok(FbbuLeaseInfo {
462 lease_id,
463 expires_at_unix_secs: expires_at as u64,
464 num_blocks: num_blocks as u64,
465 block_size: block_size as u32,
466 status: lease_status as u8,
467 }),
468 Some(e) => Err(e),
469 }
470}
471
472#[cfg(target_arch = "wasm32")]
474pub fn fbbu_renew(lease_id: u128, duration_secs: u64) -> Result<u64> {
475 let (lease_hi, lease_lo) = split_u128_words(lease_id);
476 let mut expires_at: i64 = 0;
477 let status = unsafe {
478 wasm::fbbu_renew(
479 lease_hi,
480 lease_lo,
481 duration_secs as i64,
482 &mut expires_at as *mut i64 as i32,
483 )
484 };
485 match FabricError::from_status(status) {
486 None => Ok(expires_at as u64),
487 Some(e) => Err(e),
488 }
489}
490
491#[cfg(target_arch = "wasm32")]
493pub fn fbbu_free(lease_id: u128) -> Result<()> {
494 let (lease_hi, lease_lo) = split_u128_words(lease_id);
495 let status = unsafe { wasm::fbbu_free(lease_hi, lease_lo) };
496 match FabricError::from_status(status) {
497 None => Ok(()),
498 Some(e) => Err(e),
499 }
500}
501
502#[cfg(target_arch = "wasm32")]
504pub fn fbbu_write_block_lease(lease_id: u128, lba: u64, data: &[u8; 512]) -> Result<()> {
505 let (lease_hi, lease_lo) = split_u128_words(lease_id);
506 let status = unsafe {
507 wasm::fbbu_write_block_lease(lease_hi, lease_lo, lba as i64, data.as_ptr() as i32)
508 };
509 match FabricError::from_status(status) {
510 None => Ok(()),
511 Some(e) => Err(e),
512 }
513}
514
515#[cfg(target_arch = "wasm32")]
517pub fn fbbu_read_block_lease(lease_id: u128, lba: u64, buf: &mut [u8; 512]) -> Result<()> {
518 let (lease_hi, lease_lo) = split_u128_words(lease_id);
519 let status = unsafe {
520 wasm::fbbu_read_block_lease(lease_hi, lease_lo, lba as i64, buf.as_mut_ptr() as i32)
521 };
522 match FabricError::from_status(status) {
523 None => Ok(()),
524 Some(e) => Err(e),
525 }
526}
527
528#[cfg(target_arch = "wasm32")]
533mod wasm_tasklet {
534 #[link(wasm_import_module = "fabricbios_tasklet_v0")]
535 extern "C" {
536 pub fn tasklet_submit(
540 wasm_ptr: i32,
541 wasm_len: i32,
542 input_ptr: i32,
543 input_len: i32,
544 fuel: i64,
545 exit_code_ptr: i32,
546 output_ptr: i32,
547 output_max_len: i32,
548 output_len_ptr: i32,
549 ) -> i32;
550 }
551}
552
553#[cfg(target_arch = "wasm32")]
554mod wasm_net {
555 #[link(wasm_import_module = "fabricbios_net_v0")]
556 extern "C" {
557 pub fn net_hello(
561 min_bw: i64,
562 name_ptr: i32,
563 name_max_len: i32,
564 name_len_ptr: i32,
565 bw_ptr: i32,
566 ) -> i32;
567 }
568}
569
570#[cfg(target_arch = "wasm32")]
571mod wasm_gpu {
572 #[link(wasm_import_module = "fabricbios_gpu_v0")]
573 extern "C" {
574 pub fn gpu_lease_alloc(
577 resource_id_lo: i64,
578 resource_id_hi: i64,
579 lease_secs: u32,
580 lease_id_lo_ptr: i32,
581 lease_id_hi_ptr: i32,
582 ) -> i32;
583
584 pub fn gpu_lease_renew(lease_id_lo: i64, lease_id_hi: i64, duration_secs: u32) -> i32;
586
587 pub fn gpu_lease_free(lease_id_lo: i64, lease_id_hi: i64) -> i32;
589
590 pub fn gpu_lease_query(lease_id_lo: i64, lease_id_hi: i64, status_ptr: i32) -> i32;
593 }
594
595 #[link(wasm_import_module = "fabricbios_gpu_v1")]
608 extern "C" {
609 pub fn gpu_session_mem_alloc(
610 lease_lo: i64,
611 lease_hi: i64,
612 size: i64,
613 handle_out_ptr: i32,
614 ) -> i32;
615
616 pub fn gpu_session_mem_write(
617 lease_lo: i64,
618 lease_hi: i64,
619 handle: i64,
620 offset: i64,
621 data_ptr: i32,
622 data_len: i32,
623 ) -> i32;
624
625 pub fn gpu_session_mem_read(
626 lease_lo: i64,
627 lease_hi: i64,
628 handle: i64,
629 offset: i64,
630 dst_ptr: i32,
631 dst_max: i32,
632 out_len_ptr: i32,
633 ) -> i32;
634
635 pub fn gpu_session_mem_free(lease_lo: i64, lease_hi: i64, handle: i64) -> i32;
636
637 pub fn gpu_session_module_load(
638 lease_lo: i64,
639 lease_hi: i64,
640 bin_ptr: i32,
641 bin_len: i32,
642 module_out_ptr: i32,
643 ) -> i32;
644
645 pub fn gpu_session_launch(
646 lease_lo: i64,
647 lease_hi: i64,
648 module_id: i64,
649 kname_ptr: i32,
650 kname_len: i32,
651 gx: u32,
652 gy: u32,
653 gz: u32,
654 bx: u32,
655 by: u32,
656 bz: u32,
657 args_ptr: i32,
658 args_len: i32,
659 arg_sizes_ptr: i32,
660 arg_sizes_len: i32,
661 ) -> i32;
662
663 pub fn gpu_session_sync(lease_lo: i64, lease_hi: i64) -> i32;
664
665 pub fn gpu_session_module_unload(lease_lo: i64, lease_hi: i64, module_id: i64) -> i32;
669 }
670}
671
672#[cfg(target_arch = "wasm32")]
689pub fn tasklet_submit(
690 wasm: &[u8],
691 input: &[u8],
692 fuel: u64,
693 output_buf: &mut [u8],
694) -> Result<(u64, usize)> {
695 let mut exit_code: u64 = 0;
696 let mut output_len: u32 = 0;
697 let status = unsafe {
698 wasm_tasklet::tasklet_submit(
699 wasm.as_ptr() as i32,
700 wasm.len() as i32,
701 input.as_ptr() as i32,
702 input.len() as i32,
703 fuel as i64,
704 &mut exit_code as *mut u64 as i32,
705 output_buf.as_mut_ptr() as i32,
706 output_buf.len() as i32,
707 &mut output_len as *mut u32 as i32,
708 )
709 };
710 match FabricError::from_status(status) {
711 None => Ok((exit_code, output_len as usize)),
712 Some(e) => Err(e),
713 }
714}
715
716#[cfg(target_arch = "wasm32")]
718pub fn gpu_lease_alloc(resource_id: u128, lease_secs: u32) -> Result<u128> {
719 let res_lo = resource_id as i64;
720 let res_hi = (resource_id >> 64) as i64;
721 let mut lease_id_lo: u64 = 0;
722 let mut lease_id_hi: u64 = 0;
723 let status = unsafe {
724 wasm_gpu::gpu_lease_alloc(
725 res_lo,
726 res_hi,
727 lease_secs,
728 &mut lease_id_lo as *mut u64 as i32,
729 &mut lease_id_hi as *mut u64 as i32,
730 )
731 };
732 match FabricError::from_status(status) {
733 None => Ok((lease_id_hi as u128) << 64 | (lease_id_lo as u128)),
734 Some(e) => Err(e),
735 }
736}
737
738#[cfg(target_arch = "wasm32")]
740pub fn gpu_lease_renew(lease_id: u128, duration_secs: u32) -> Result<()> {
741 let lo = lease_id as i64;
742 let hi = (lease_id >> 64) as i64;
743 let status = unsafe { wasm_gpu::gpu_lease_renew(lo, hi, duration_secs) };
744 match FabricError::from_status(status) {
745 None => Ok(()),
746 Some(e) => Err(e),
747 }
748}
749
750#[cfg(target_arch = "wasm32")]
752pub fn gpu_lease_free(lease_id: u128) -> Result<()> {
753 let lo = lease_id as i64;
754 let hi = (lease_id >> 64) as i64;
755 let status = unsafe { wasm_gpu::gpu_lease_free(lo, hi) };
756 match FabricError::from_status(status) {
757 None => Ok(()),
758 Some(e) => Err(e),
759 }
760}
761
762#[cfg(target_arch = "wasm32")]
765pub fn gpu_lease_query(lease_id: u128) -> Result<u32> {
766 let lo = lease_id as i64;
767 let hi = (lease_id >> 64) as i64;
768 let mut lease_status: u32 = 0;
769 let status = unsafe { wasm_gpu::gpu_lease_query(lo, hi, &mut lease_status as *mut u32 as i32) };
770 match FabricError::from_status(status) {
771 None => Ok(lease_status),
772 Some(e) => Err(e),
773 }
774}
775
776#[cfg(target_arch = "wasm32")]
794#[inline]
795fn lease_id_split(lease_id: u128) -> (i64, i64) {
796 (lease_id as i64, (lease_id >> 64) as i64)
797}
798
799#[inline]
809fn session_status_to_result(status: i32) -> Result<()> {
810 if status == 0 {
811 Ok(())
812 } else if status < 0 {
813 Err(FabricError::from_status(status).unwrap_or(FabricError::IoError(status)))
815 } else {
816 Err(FabricError::GpuSessionFailed(status as u8))
819 }
820}
821
822#[cfg(target_arch = "wasm32")]
824pub fn gpu_session_mem_alloc(lease_id: u128, size: u64) -> Result<u64> {
825 let (lo, hi) = lease_id_split(lease_id);
826 let mut handle: u64 = 0;
827 let status = unsafe {
828 wasm_gpu::gpu_session_mem_alloc(lo, hi, size as i64, &mut handle as *mut u64 as i32)
829 };
830 session_status_to_result(status).map(|()| handle)
831}
832
833#[cfg(target_arch = "wasm32")]
835pub fn gpu_session_mem_write(lease_id: u128, handle: u64, offset: u64, data: &[u8]) -> Result<()> {
836 let (lo, hi) = lease_id_split(lease_id);
837 let status = unsafe {
838 wasm_gpu::gpu_session_mem_write(
839 lo,
840 hi,
841 handle as i64,
842 offset as i64,
843 data.as_ptr() as i32,
844 data.len() as i32,
845 )
846 };
847 session_status_to_result(status)
848}
849
850#[cfg(target_arch = "wasm32")]
856pub fn gpu_session_mem_read(
857 lease_id: u128,
858 handle: u64,
859 offset: u64,
860 size: u32,
861) -> Result<alloc::vec::Vec<u8>> {
862 let (lo, hi) = lease_id_split(lease_id);
863 let mut buf: alloc::vec::Vec<u8> = alloc::vec![0u8; size as usize];
864 let mut out_len: u32 = 0;
865 let status = unsafe {
866 wasm_gpu::gpu_session_mem_read(
867 lo,
868 hi,
869 handle as i64,
870 offset as i64,
871 buf.as_mut_ptr() as i32,
872 size as i32,
873 &mut out_len as *mut u32 as i32,
874 )
875 };
876 session_status_to_result(status).map(|()| {
877 buf.truncate(out_len as usize);
878 buf
879 })
880}
881
882#[cfg(target_arch = "wasm32")]
884pub fn gpu_session_mem_free(lease_id: u128, handle: u64) -> Result<()> {
885 let (lo, hi) = lease_id_split(lease_id);
886 let status = unsafe { wasm_gpu::gpu_session_mem_free(lo, hi, handle as i64) };
887 session_status_to_result(status)
888}
889
890#[cfg(target_arch = "wasm32")]
892pub fn gpu_session_module_load(lease_id: u128, binary: &[u8]) -> Result<u64> {
893 let (lo, hi) = lease_id_split(lease_id);
894 let mut module_id: u64 = 0;
895 let status = unsafe {
896 wasm_gpu::gpu_session_module_load(
897 lo,
898 hi,
899 binary.as_ptr() as i32,
900 binary.len() as i32,
901 &mut module_id as *mut u64 as i32,
902 )
903 };
904 session_status_to_result(status).map(|()| module_id)
905}
906
907#[cfg(target_arch = "wasm32")]
909pub fn gpu_session_launch(
910 lease_id: u128,
911 module_id: u64,
912 kernel_name: &str,
913 grid_dim: [u32; 3],
914 block_dim: [u32; 3],
915 args: &[u8],
916 arg_sizes: &[u32],
917) -> Result<()> {
918 let (lo, hi) = lease_id_split(lease_id);
919 let name_bytes = kernel_name.as_bytes();
920 let status = unsafe {
921 wasm_gpu::gpu_session_launch(
922 lo,
923 hi,
924 module_id as i64,
925 name_bytes.as_ptr() as i32,
926 name_bytes.len() as i32,
927 grid_dim[0],
928 grid_dim[1],
929 grid_dim[2],
930 block_dim[0],
931 block_dim[1],
932 block_dim[2],
933 args.as_ptr() as i32,
934 args.len() as i32,
935 arg_sizes.as_ptr() as i32,
936 arg_sizes.len() as i32,
937 )
938 };
939 session_status_to_result(status)
940}
941
942#[cfg(target_arch = "wasm32")]
944pub fn gpu_session_sync(lease_id: u128) -> Result<()> {
945 let (lo, hi) = lease_id_split(lease_id);
946 let status = unsafe { wasm_gpu::gpu_session_sync(lo, hi) };
947 session_status_to_result(status)
948}
949
950#[cfg(target_arch = "wasm32")]
952pub fn gpu_session_module_unload(lease_id: u128, module_id: u64) -> Result<()> {
953 let (lo, hi) = lease_id_split(lease_id);
954 let status = unsafe { wasm_gpu::gpu_session_module_unload(lo, hi, module_id as i64) };
955 session_status_to_result(status)
956}
957
958#[cfg(target_arch = "wasm32")]
972pub fn net_hello(min_bw: u64) -> Result<(alloc::string::String, u64)> {
973 let mut name_buf = [0u8; 64];
974 let mut name_len: u32 = 0;
975 let mut actual_bw: u64 = 0;
976 let status = unsafe {
977 wasm_net::net_hello(
978 min_bw as i64,
979 name_buf.as_mut_ptr() as i32,
980 name_buf.len() as i32,
981 &mut name_len as *mut u32 as i32,
982 &mut actual_bw as *mut u64 as i32,
983 )
984 };
985 match FabricError::from_status(status) {
986 None => {
987 let name = core::str::from_utf8(&name_buf[..name_len as usize]).unwrap_or("unknown");
988 Ok((alloc::string::String::from(name), actual_bw))
989 }
990 Some(e) => Err(e),
991 }
992}
993
994#[cfg(not(target_arch = "wasm32"))]
999mod mock {
1000 extern crate alloc;
1001 use super::{LEASE_STATUS_ACTIVE, LEASE_STATUS_EXPIRED, LEASE_STATUS_REVOKED};
1002 use alloc::collections::BTreeMap;
1003 use alloc::vec::Vec;
1004
1005 pub struct MockFbmu {
1006 pub arena: BTreeMap<u64, Vec<u8>>,
1007 pub arena_size: u64,
1008 pub hello_called: bool,
1009 }
1010
1011 impl Default for MockFbmu {
1012 fn default() -> Self {
1013 MockFbmu {
1014 arena: BTreeMap::new(),
1015 arena_size: 65536,
1016 hello_called: false,
1017 }
1018 }
1019 }
1020
1021 pub struct MockFbbu {
1022 pub blocks: BTreeMap<u64, [u8; 512]>,
1023 pub num_blocks: u64,
1024 pub hello_called: bool,
1025 }
1026
1027 impl Default for MockFbbu {
1028 fn default() -> Self {
1029 MockFbbu {
1030 blocks: BTreeMap::new(),
1031 num_blocks: 1024,
1032 hello_called: false,
1033 }
1034 }
1035 }
1036
1037 pub struct MockFbmuLease {
1038 pub status: u8,
1039 pub expires_at_unix_secs: u64,
1040 pub arena_size: u64,
1041 pub arena: BTreeMap<u64, Vec<u8>>,
1042 }
1043
1044 pub struct MockFbbuLease {
1045 pub status: u8,
1046 pub expires_at_unix_secs: u64,
1047 pub block_size: u32,
1048 pub num_blocks: u64,
1049 pub blocks: BTreeMap<u64, [u8; 512]>,
1050 }
1051
1052 #[derive(Default)]
1053 pub struct MockTasklet {
1054 pub exit_code: u64,
1056 pub output: Vec<u8>,
1058 pub submit_count: u64,
1060 }
1061
1062 #[derive(Default)]
1063 pub struct MockGpu {
1064 pub session_next_handle: u64,
1066 pub session_next_module: u64,
1068 pub session_op_count: u64,
1070 pub session_mem_free_count: u64,
1074 pub session_module_unload_count: u64,
1078 pub session_error: Option<i32>,
1080 pub lease_next_id: u128,
1082 pub lease_active: BTreeMap<u128, ()>,
1084 pub lease_error: Option<i32>,
1086 }
1087
1088 pub struct MockNet {
1089 pub interface_name: alloc::string::String,
1091 pub bandwidth: u64,
1093 }
1094
1095 impl Default for MockNet {
1096 fn default() -> Self {
1097 MockNet {
1098 interface_name: alloc::string::String::from("eth-mock0"),
1099 bandwidth: 1_000_000_000,
1100 }
1101 }
1102 }
1103
1104 pub struct MockState {
1105 pub fbmu: MockFbmu,
1106 pub fbbu: MockFbbu,
1107 pub fbmu_leases: BTreeMap<u128, MockFbmuLease>,
1108 pub fbbu_leases: BTreeMap<u128, MockFbbuLease>,
1109 pub next_lease_seq: u64,
1110 pub tasklet: MockTasklet,
1111 pub gpu: MockGpu,
1112 pub net: MockNet,
1113 pub now_unix_secs: u64,
1115 pub fbmu_hello_error: Option<i32>,
1117 pub fbbu_hello_error: Option<i32>,
1119 pub tasklet_submit_error: Option<i32>,
1121 pub net_hello_error: Option<i32>,
1123 }
1124
1125 impl Default for MockState {
1126 fn default() -> Self {
1127 MockState {
1128 fbmu: MockFbmu::default(),
1129 fbbu: MockFbbu::default(),
1130 fbmu_leases: BTreeMap::new(),
1131 fbbu_leases: BTreeMap::new(),
1132 next_lease_seq: 1,
1133 tasklet: MockTasklet::default(),
1134 gpu: MockGpu::default(),
1135 net: MockNet::default(),
1136 now_unix_secs: 1_700_000_000,
1137 fbmu_hello_error: None,
1138 fbbu_hello_error: None,
1139 tasklet_submit_error: None,
1140 net_hello_error: None,
1141 }
1142 }
1143 }
1144
1145 #[cfg(feature = "std")]
1146 thread_local! {
1147 pub static MOCK: std::cell::RefCell<MockState> = std::cell::RefCell::new(MockState::default());
1148 }
1149
1150 #[cfg(not(feature = "std"))]
1153 mod nostd_mock {
1154 use super::MockState;
1155 use core::sync::atomic::{AtomicBool, Ordering};
1156
1157 static LOCK: AtomicBool = AtomicBool::new(false);
1158 static mut STATE: Option<MockState> = None;
1159
1160 pub fn with_mock<F, R>(f: F) -> R
1161 where
1162 F: FnOnce(&mut MockState) -> R,
1163 {
1164 while LOCK
1165 .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
1166 .is_err()
1167 {
1168 core::hint::spin_loop();
1169 }
1170 let state = unsafe {
1171 if STATE.is_none() {
1172 STATE = Some(MockState::default());
1173 }
1174 STATE.as_mut().unwrap()
1175 };
1176 let result = f(state);
1177 LOCK.store(false, Ordering::Release);
1178 result
1179 }
1180 }
1181
1182 pub fn with_mock<F, R>(f: F) -> R
1183 where
1184 F: FnOnce(&mut MockState) -> R,
1185 {
1186 #[cfg(feature = "std")]
1187 {
1188 MOCK.with(|cell| f(&mut cell.borrow_mut()))
1189 }
1190 #[cfg(not(feature = "std"))]
1191 {
1192 nostd_mock::with_mock(f)
1193 }
1194 }
1195
1196 fn next_lease_id(state: &mut MockState, tag: u8) -> u128 {
1197 let seq = state.next_lease_seq as u128;
1198 state.next_lease_seq = state.next_lease_seq.saturating_add(1);
1199 ((state.now_unix_secs as u128) << 64) | ((tag as u128) << 56) | seq
1200 }
1201
1202 fn refresh_fbmu_leases(state: &mut MockState) {
1203 let now = state.now_unix_secs;
1204 for lease in state.fbmu_leases.values_mut() {
1205 if lease.status == LEASE_STATUS_ACTIVE && now >= lease.expires_at_unix_secs {
1206 lease.status = LEASE_STATUS_EXPIRED;
1207 }
1208 }
1209 }
1210
1211 fn refresh_fbbu_leases(state: &mut MockState) {
1212 let now = state.now_unix_secs;
1213 for lease in state.fbbu_leases.values_mut() {
1214 if lease.status == LEASE_STATUS_ACTIVE && now >= lease.expires_at_unix_secs {
1215 lease.status = LEASE_STATUS_EXPIRED;
1216 }
1217 }
1218 }
1219
1220 pub fn fbmu_hello_impl() -> i32 {
1221 with_mock(|s| {
1222 if let Some(err) = s.fbmu_hello_error {
1223 return err;
1224 }
1225 s.fbmu.hello_called = true;
1226 0
1227 })
1228 }
1229
1230 pub fn fbmu_write_impl(offset: u64, data: &[u8]) -> i32 {
1231 with_mock(|s| {
1232 s.fbmu.arena.insert(offset, data.to_vec());
1233 0
1234 })
1235 }
1236
1237 pub fn fbmu_read_impl(offset: u64, buf: &mut [u8]) -> i32 {
1238 with_mock(|s| {
1239 if let Some(data) = s.fbmu.arena.get(&offset) {
1240 let len = buf.len().min(data.len());
1241 buf[..len].copy_from_slice(&data[..len]);
1242 len as i32
1243 } else {
1244 for b in buf.iter_mut() {
1246 *b = 0;
1247 }
1248 buf.len() as i32
1249 }
1250 })
1251 }
1252
1253 pub fn fbmu_get_arena_size_impl() -> i64 {
1254 with_mock(|s| s.fbmu.arena_size as i64)
1255 }
1256
1257 pub fn fbmu_alloc_impl(min_bytes: u64, lease_secs: u64) -> (i32, u128, u64, u64) {
1258 with_mock(|s| {
1259 if s.fbmu.arena_size < min_bytes {
1260 return (-4, 0, 0, 0);
1261 }
1262 let lease_id = next_lease_id(s, 0x01);
1263 let expires = s.now_unix_secs.saturating_add(lease_secs.max(1));
1264 let lease = MockFbmuLease {
1265 status: LEASE_STATUS_ACTIVE,
1266 expires_at_unix_secs: expires,
1267 arena_size: s.fbmu.arena_size,
1268 arena: BTreeMap::new(),
1269 };
1270 s.fbmu_leases.insert(lease_id, lease);
1271 (0, lease_id, expires, s.fbmu.arena_size)
1272 })
1273 }
1274
1275 pub fn fbmu_query_impl(lease_id: u128) -> (i32, u8, u64, u64) {
1276 with_mock(|s| {
1277 refresh_fbmu_leases(s);
1278 let Some(lease) = s.fbmu_leases.get(&lease_id) else {
1279 return (-2, LEASE_STATUS_REVOKED, 0, 0);
1280 };
1281 (
1282 0,
1283 lease.status,
1284 lease.expires_at_unix_secs,
1285 lease.arena_size,
1286 )
1287 })
1288 }
1289
1290 pub fn fbmu_renew_impl(lease_id: u128, duration_secs: u64) -> (i32, u64) {
1291 with_mock(|s| {
1292 if duration_secs == 0 {
1293 return (-1, 0);
1294 }
1295 refresh_fbmu_leases(s);
1296 let Some(lease) = s.fbmu_leases.get_mut(&lease_id) else {
1297 return (-2, 0);
1298 };
1299 if lease.status != LEASE_STATUS_ACTIVE {
1300 return (-2, lease.expires_at_unix_secs);
1301 }
1302 let requested_exp = s.now_unix_secs.saturating_add(duration_secs);
1303 if requested_exp > lease.expires_at_unix_secs {
1304 lease.expires_at_unix_secs = requested_exp;
1305 }
1306 (0, lease.expires_at_unix_secs)
1307 })
1308 }
1309
1310 pub fn fbmu_free_impl(lease_id: u128) -> i32 {
1311 with_mock(|s| {
1312 refresh_fbmu_leases(s);
1313 let Some(lease) = s.fbmu_leases.get_mut(&lease_id) else {
1314 return -2;
1315 };
1316 lease.status = LEASE_STATUS_REVOKED;
1317 0
1318 })
1319 }
1320
1321 pub fn fbmu_write_lease_impl(lease_id: u128, offset: u64, data: &[u8]) -> i32 {
1322 with_mock(|s| {
1323 refresh_fbmu_leases(s);
1324 let Some(lease) = s.fbmu_leases.get_mut(&lease_id) else {
1325 return -2;
1326 };
1327 if lease.status != LEASE_STATUS_ACTIVE {
1328 return -2;
1329 }
1330 let end = match offset.checked_add(data.len() as u64) {
1331 Some(v) => v,
1332 None => return -4,
1333 };
1334 if end > lease.arena_size {
1335 return -4;
1336 }
1337 lease.arena.insert(offset, data.to_vec());
1338 0
1339 })
1340 }
1341
1342 pub fn fbmu_read_lease_impl(lease_id: u128, offset: u64, buf: &mut [u8]) -> i32 {
1343 with_mock(|s| {
1344 refresh_fbmu_leases(s);
1345 let Some(lease) = s.fbmu_leases.get_mut(&lease_id) else {
1346 return -2;
1347 };
1348 if lease.status != LEASE_STATUS_ACTIVE {
1349 return -2;
1350 }
1351 if offset >= lease.arena_size {
1352 return -4;
1353 }
1354 let max_len = (lease.arena_size - offset) as usize;
1355 let read_len = buf.len().min(max_len);
1356 for b in buf.iter_mut().take(read_len) {
1357 *b = 0;
1358 }
1359 if let Some(data) = lease.arena.get(&offset) {
1360 let copy_len = read_len.min(data.len());
1361 buf[..copy_len].copy_from_slice(&data[..copy_len]);
1362 }
1363 read_len as i32
1364 })
1365 }
1366
1367 pub fn fbbu_hello_impl() -> i32 {
1368 with_mock(|s| {
1369 if let Some(err) = s.fbbu_hello_error {
1370 return err;
1371 }
1372 s.fbbu.hello_called = true;
1373 0
1374 })
1375 }
1376
1377 pub fn fbbu_write_block_impl(lba: u64, data: &[u8; 512]) -> i32 {
1378 with_mock(|s| {
1379 if lba >= s.fbbu.num_blocks {
1380 return -4; }
1382 s.fbbu.blocks.insert(lba, *data);
1383 0
1384 })
1385 }
1386
1387 pub fn fbbu_read_block_impl(lba: u64, buf: &mut [u8; 512]) -> i32 {
1388 with_mock(|s| {
1389 if lba >= s.fbbu.num_blocks {
1390 return -4; }
1392 if let Some(block) = s.fbbu.blocks.get(&lba) {
1393 *buf = *block;
1394 } else {
1395 *buf = [0u8; 512];
1396 }
1397 0
1398 })
1399 }
1400
1401 pub fn fbbu_get_num_blocks_impl() -> i64 {
1402 with_mock(|s| s.fbbu.num_blocks as i64)
1403 }
1404
1405 pub fn fbbu_alloc_impl(min_blocks: u64, lease_secs: u64) -> (i32, u128, u64, u64, u32) {
1406 with_mock(|s| {
1407 if s.fbbu.num_blocks < min_blocks {
1408 return (-4, 0, 0, 0, 0);
1409 }
1410 let lease_id = next_lease_id(s, 0x02);
1411 let expires = s.now_unix_secs.saturating_add(lease_secs.max(1));
1412 let lease = MockFbbuLease {
1413 status: LEASE_STATUS_ACTIVE,
1414 expires_at_unix_secs: expires,
1415 block_size: 512,
1416 num_blocks: s.fbbu.num_blocks,
1417 blocks: BTreeMap::new(),
1418 };
1419 s.fbbu_leases.insert(lease_id, lease);
1420 (0, lease_id, expires, s.fbbu.num_blocks, 512)
1421 })
1422 }
1423
1424 pub fn fbbu_query_impl(lease_id: u128) -> (i32, u8, u64, u64, u32) {
1425 with_mock(|s| {
1426 refresh_fbbu_leases(s);
1427 let Some(lease) = s.fbbu_leases.get(&lease_id) else {
1428 return (-2, LEASE_STATUS_REVOKED, 0, 0, 0);
1429 };
1430 (
1431 0,
1432 lease.status,
1433 lease.expires_at_unix_secs,
1434 lease.num_blocks,
1435 lease.block_size,
1436 )
1437 })
1438 }
1439
1440 pub fn fbbu_renew_impl(lease_id: u128, duration_secs: u64) -> (i32, u64) {
1441 with_mock(|s| {
1442 if duration_secs == 0 {
1443 return (-1, 0);
1444 }
1445 refresh_fbbu_leases(s);
1446 let Some(lease) = s.fbbu_leases.get_mut(&lease_id) else {
1447 return (-2, 0);
1448 };
1449 if lease.status != LEASE_STATUS_ACTIVE {
1450 return (-2, lease.expires_at_unix_secs);
1451 }
1452 let requested_exp = s.now_unix_secs.saturating_add(duration_secs);
1453 if requested_exp > lease.expires_at_unix_secs {
1454 lease.expires_at_unix_secs = requested_exp;
1455 }
1456 (0, lease.expires_at_unix_secs)
1457 })
1458 }
1459
1460 pub fn fbbu_free_impl(lease_id: u128) -> i32 {
1461 with_mock(|s| {
1462 refresh_fbbu_leases(s);
1463 let Some(lease) = s.fbbu_leases.get_mut(&lease_id) else {
1464 return -2;
1465 };
1466 lease.status = LEASE_STATUS_REVOKED;
1467 0
1468 })
1469 }
1470
1471 pub fn fbbu_write_block_lease_impl(lease_id: u128, lba: u64, data: &[u8; 512]) -> i32 {
1472 with_mock(|s| {
1473 refresh_fbbu_leases(s);
1474 let Some(lease) = s.fbbu_leases.get_mut(&lease_id) else {
1475 return -2;
1476 };
1477 if lease.status != LEASE_STATUS_ACTIVE {
1478 return -2;
1479 }
1480 if lba >= lease.num_blocks {
1481 return -4;
1482 }
1483 lease.blocks.insert(lba, *data);
1484 0
1485 })
1486 }
1487
1488 pub fn fbbu_read_block_lease_impl(lease_id: u128, lba: u64, buf: &mut [u8; 512]) -> i32 {
1489 with_mock(|s| {
1490 refresh_fbbu_leases(s);
1491 let Some(lease) = s.fbbu_leases.get_mut(&lease_id) else {
1492 return -2;
1493 };
1494 if lease.status != LEASE_STATUS_ACTIVE {
1495 return -2;
1496 }
1497 if lba >= lease.num_blocks {
1498 return -4;
1499 }
1500 if let Some(block) = lease.blocks.get(&lba) {
1501 *buf = *block;
1502 } else {
1503 *buf = [0u8; 512];
1504 }
1505 0
1506 })
1507 }
1508
1509 pub fn tasklet_submit_impl(
1510 _wasm: &[u8],
1511 _input: &[u8],
1512 _fuel: u64,
1513 output_buf: &mut [u8],
1514 ) -> (i32, u64, usize) {
1515 with_mock(|s| {
1516 if let Some(err) = s.tasklet_submit_error {
1517 return (err, 0, 0);
1518 }
1519 s.tasklet.submit_count += 1;
1520 let out_len = output_buf.len().min(s.tasklet.output.len());
1521 output_buf[..out_len].copy_from_slice(&s.tasklet.output[..out_len]);
1522 (0, s.tasklet.exit_code, out_len)
1523 })
1524 }
1525
1526 pub fn gpu_session_mem_alloc_impl(_lease_id: u128, _size: u64) -> (i32, u64) {
1529 with_mock(|s| {
1530 if let Some(err) = s.gpu.session_error {
1531 return (err, 0);
1532 }
1533 s.gpu.session_next_handle += 1;
1534 s.gpu.session_op_count += 1;
1535 (0, s.gpu.session_next_handle)
1536 })
1537 }
1538
1539 pub fn gpu_session_mem_write_impl(
1540 _lease_id: u128,
1541 _handle: u64,
1542 _offset: u64,
1543 _data: &[u8],
1544 ) -> i32 {
1545 with_mock(|s| {
1546 if let Some(err) = s.gpu.session_error {
1547 return err;
1548 }
1549 s.gpu.session_op_count += 1;
1550 0
1551 })
1552 }
1553
1554 pub fn gpu_session_mem_read_impl(
1555 _lease_id: u128,
1556 _handle: u64,
1557 _offset: u64,
1558 size: u32,
1559 ) -> (i32, Vec<u8>) {
1560 with_mock(|s| {
1561 if let Some(err) = s.gpu.session_error {
1562 return (err, Vec::new());
1563 }
1564 s.gpu.session_op_count += 1;
1565 (0, alloc::vec![0u8; size as usize])
1566 })
1567 }
1568
1569 pub fn gpu_session_mem_free_impl(_lease_id: u128, _handle: u64) -> i32 {
1570 with_mock(|s| {
1571 if let Some(err) = s.gpu.session_error {
1572 return err;
1573 }
1574 s.gpu.session_op_count += 1;
1575 s.gpu.session_mem_free_count += 1;
1576 0
1577 })
1578 }
1579
1580 pub fn gpu_session_module_load_impl(_lease_id: u128, _binary: &[u8]) -> (i32, u64) {
1581 with_mock(|s| {
1582 if let Some(err) = s.gpu.session_error {
1583 return (err, 0);
1584 }
1585 s.gpu.session_next_module += 1;
1586 s.gpu.session_op_count += 1;
1587 (0, s.gpu.session_next_module)
1588 })
1589 }
1590
1591 pub fn gpu_session_launch_impl(
1592 _lease_id: u128,
1593 _module_id: u64,
1594 _kernel_name: &str,
1595 _grid_dim: [u32; 3],
1596 _block_dim: [u32; 3],
1597 _args: &[u8],
1598 _arg_sizes: &[u32],
1599 ) -> i32 {
1600 with_mock(|s| {
1601 if let Some(err) = s.gpu.session_error {
1602 return err;
1603 }
1604 s.gpu.session_op_count += 1;
1605 0
1606 })
1607 }
1608
1609 pub fn gpu_session_sync_impl(_lease_id: u128) -> i32 {
1610 with_mock(|s| {
1611 if let Some(err) = s.gpu.session_error {
1612 return err;
1613 }
1614 s.gpu.session_op_count += 1;
1615 0
1616 })
1617 }
1618
1619 pub fn gpu_session_module_unload_impl(_lease_id: u128, _module_id: u64) -> i32 {
1620 with_mock(|s| {
1621 if let Some(err) = s.gpu.session_error {
1622 return err;
1623 }
1624 s.gpu.session_op_count += 1;
1625 s.gpu.session_module_unload_count += 1;
1626 0
1627 })
1628 }
1629
1630 pub fn gpu_lease_alloc_impl(_resource_id: u128, _lease_secs: u32) -> (i32, u128) {
1633 with_mock(|s| {
1634 if let Some(err) = s.gpu.lease_error {
1635 return (err, 0);
1636 }
1637 s.gpu.lease_next_id += 1;
1638 let id = s.gpu.lease_next_id;
1639 s.gpu.lease_active.insert(id, ());
1640 (0, id)
1641 })
1642 }
1643
1644 pub fn gpu_lease_renew_impl(lease_id: u128, _duration_secs: u32) -> i32 {
1645 with_mock(|s| {
1646 if let Some(err) = s.gpu.lease_error {
1647 return err;
1648 }
1649 if s.gpu.lease_active.contains_key(&lease_id) {
1650 0
1651 } else {
1652 -1
1653 }
1654 })
1655 }
1656
1657 pub fn gpu_lease_free_impl(lease_id: u128) -> i32 {
1658 with_mock(|s| {
1659 if let Some(err) = s.gpu.lease_error {
1660 return err;
1661 }
1662 s.gpu.lease_active.remove(&lease_id);
1663 0
1664 })
1665 }
1666
1667 pub fn gpu_lease_query_impl(lease_id: u128) -> (i32, u32) {
1668 with_mock(|s| {
1669 if let Some(err) = s.gpu.lease_error {
1670 return (err, 0);
1671 }
1672 if s.gpu.lease_active.contains_key(&lease_id) {
1673 (0, 0) } else {
1675 (0, 1) }
1677 })
1678 }
1679
1680 pub fn net_hello_impl(_min_bw: u64) -> (i32, alloc::string::String, u64) {
1681 with_mock(|s| {
1682 if let Some(err) = s.net_hello_error {
1683 return (err, alloc::string::String::new(), 0);
1684 }
1685 (0, s.net.interface_name.clone(), s.net.bandwidth)
1686 })
1687 }
1688
1689 pub fn _set_gpu_session_error(err: Option<i32>) {
1694 with_mock(|s| s.gpu.session_error = err);
1695 }
1696
1697 pub fn _gpu_session_op_count() -> u64 {
1701 with_mock(|s| s.gpu.session_op_count)
1702 }
1703
1704 pub fn _gpu_session_mem_free_count() -> u64 {
1709 with_mock(|s| s.gpu.session_mem_free_count)
1710 }
1711
1712 pub fn _gpu_session_module_unload_count() -> u64 {
1716 with_mock(|s| s.gpu.session_module_unload_count)
1717 }
1718}
1719
1720#[cfg(not(target_arch = "wasm32"))]
1723#[doc(hidden)]
1724pub mod test_mock {
1725 pub use super::mock::{
1726 _gpu_session_mem_free_count, _gpu_session_module_unload_count, _gpu_session_op_count,
1727 _set_gpu_session_error,
1728 };
1729}
1730
1731#[cfg(not(target_arch = "wasm32"))]
1742pub fn fbmu_hello() -> Result<()> {
1743 let status = mock::fbmu_hello_impl();
1744 match FabricError::from_status(status) {
1745 None => Ok(()),
1746 Some(e) => Err(e),
1747 }
1748}
1749
1750#[cfg(not(target_arch = "wasm32"))]
1756pub fn fbmu_write(offset: u64, data: &[u8]) -> Result<()> {
1757 let status = mock::fbmu_write_impl(offset, data);
1758 match FabricError::from_status(status) {
1759 None => Ok(()),
1760 Some(e) => Err(e),
1761 }
1762}
1763
1764#[cfg(not(target_arch = "wasm32"))]
1773pub fn fbmu_read(offset: u64, buf: &mut [u8]) -> Result<usize> {
1774 let n = mock::fbmu_read_impl(offset, buf);
1775 if n < 0 {
1776 Err(FabricError::from_status(n).unwrap_or(FabricError::IoError(n)))
1777 } else {
1778 Ok(n as usize)
1779 }
1780}
1781
1782#[cfg(not(target_arch = "wasm32"))]
1788pub fn fbmu_get_arena_size() -> Result<u64> {
1789 let size = mock::fbmu_get_arena_size_impl();
1790 if size < 0 {
1791 Err(FabricError::IoError(size as i32))
1792 } else {
1793 Ok(size as u64)
1794 }
1795}
1796
1797#[cfg(not(target_arch = "wasm32"))]
1799pub fn fbmu_alloc(min_bytes: u64, lease_secs: u64) -> Result<FbmuLeaseInfo> {
1800 let (status, lease_id, expires_at_unix_secs, arena_size) =
1801 mock::fbmu_alloc_impl(min_bytes, lease_secs);
1802 match FabricError::from_status(status) {
1803 None => Ok(FbmuLeaseInfo {
1804 lease_id,
1805 expires_at_unix_secs,
1806 arena_size,
1807 status: LEASE_STATUS_ACTIVE,
1808 }),
1809 Some(e) => Err(e),
1810 }
1811}
1812
1813#[cfg(not(target_arch = "wasm32"))]
1815pub fn fbmu_query(lease_id: u128) -> Result<FbmuLeaseInfo> {
1816 let (status, lease_status, expires_at_unix_secs, arena_size) = mock::fbmu_query_impl(lease_id);
1817 match FabricError::from_status(status) {
1818 None => Ok(FbmuLeaseInfo {
1819 lease_id,
1820 expires_at_unix_secs,
1821 arena_size,
1822 status: lease_status,
1823 }),
1824 Some(e) => Err(e),
1825 }
1826}
1827
1828#[cfg(not(target_arch = "wasm32"))]
1830pub fn fbmu_renew(lease_id: u128, duration_secs: u64) -> Result<u64> {
1831 let (status, expires_at_unix_secs) = mock::fbmu_renew_impl(lease_id, duration_secs);
1832 match FabricError::from_status(status) {
1833 None => Ok(expires_at_unix_secs),
1834 Some(e) => Err(e),
1835 }
1836}
1837
1838#[cfg(not(target_arch = "wasm32"))]
1840pub fn fbmu_free(lease_id: u128) -> Result<()> {
1841 let status = mock::fbmu_free_impl(lease_id);
1842 match FabricError::from_status(status) {
1843 None => Ok(()),
1844 Some(e) => Err(e),
1845 }
1846}
1847
1848#[cfg(not(target_arch = "wasm32"))]
1850pub fn fbmu_write_lease(lease_id: u128, offset: u64, data: &[u8]) -> Result<()> {
1851 let status = mock::fbmu_write_lease_impl(lease_id, offset, data);
1852 match FabricError::from_status(status) {
1853 None => Ok(()),
1854 Some(e) => Err(e),
1855 }
1856}
1857
1858#[cfg(not(target_arch = "wasm32"))]
1860pub fn fbmu_read_lease(lease_id: u128, offset: u64, buf: &mut [u8]) -> Result<usize> {
1861 let n = mock::fbmu_read_lease_impl(lease_id, offset, buf);
1862 if n < 0 {
1863 Err(FabricError::from_status(n).unwrap_or(FabricError::IoError(n)))
1864 } else {
1865 Ok(n as usize)
1866 }
1867}
1868
1869#[cfg(not(target_arch = "wasm32"))]
1879pub fn fbbu_hello() -> Result<()> {
1880 let status = mock::fbbu_hello_impl();
1881 match FabricError::from_status(status) {
1882 None => Ok(()),
1883 Some(e) => Err(e),
1884 }
1885}
1886
1887#[cfg(not(target_arch = "wasm32"))]
1894pub fn fbbu_write_block(lba: u64, data: &[u8; 512]) -> Result<()> {
1895 let status = mock::fbbu_write_block_impl(lba, data);
1896 match FabricError::from_status(status) {
1897 None => Ok(()),
1898 Some(e) => Err(e),
1899 }
1900}
1901
1902#[cfg(not(target_arch = "wasm32"))]
1909pub fn fbbu_read_block(lba: u64, buf: &mut [u8; 512]) -> Result<()> {
1910 let status = mock::fbbu_read_block_impl(lba, buf);
1911 match FabricError::from_status(status) {
1912 None => Ok(()),
1913 Some(e) => Err(e),
1914 }
1915}
1916
1917#[cfg(not(target_arch = "wasm32"))]
1923pub fn fbbu_get_num_blocks() -> Result<u64> {
1924 let n = mock::fbbu_get_num_blocks_impl();
1925 if n < 0 {
1926 Err(FabricError::IoError(n as i32))
1927 } else {
1928 Ok(n as u64)
1929 }
1930}
1931
1932#[cfg(not(target_arch = "wasm32"))]
1934pub fn fbbu_alloc(min_blocks: u64, lease_secs: u64) -> Result<FbbuLeaseInfo> {
1935 let (status, lease_id, expires_at_unix_secs, num_blocks, block_size) =
1936 mock::fbbu_alloc_impl(min_blocks, lease_secs);
1937 match FabricError::from_status(status) {
1938 None => Ok(FbbuLeaseInfo {
1939 lease_id,
1940 expires_at_unix_secs,
1941 num_blocks,
1942 block_size,
1943 status: LEASE_STATUS_ACTIVE,
1944 }),
1945 Some(e) => Err(e),
1946 }
1947}
1948
1949#[cfg(not(target_arch = "wasm32"))]
1951pub fn fbbu_query(lease_id: u128) -> Result<FbbuLeaseInfo> {
1952 let (status, lease_status, expires_at_unix_secs, num_blocks, block_size) =
1953 mock::fbbu_query_impl(lease_id);
1954 match FabricError::from_status(status) {
1955 None => Ok(FbbuLeaseInfo {
1956 lease_id,
1957 expires_at_unix_secs,
1958 num_blocks,
1959 block_size,
1960 status: lease_status,
1961 }),
1962 Some(e) => Err(e),
1963 }
1964}
1965
1966#[cfg(not(target_arch = "wasm32"))]
1968pub fn fbbu_renew(lease_id: u128, duration_secs: u64) -> Result<u64> {
1969 let (status, expires_at_unix_secs) = mock::fbbu_renew_impl(lease_id, duration_secs);
1970 match FabricError::from_status(status) {
1971 None => Ok(expires_at_unix_secs),
1972 Some(e) => Err(e),
1973 }
1974}
1975
1976#[cfg(not(target_arch = "wasm32"))]
1978pub fn fbbu_free(lease_id: u128) -> Result<()> {
1979 let status = mock::fbbu_free_impl(lease_id);
1980 match FabricError::from_status(status) {
1981 None => Ok(()),
1982 Some(e) => Err(e),
1983 }
1984}
1985
1986#[cfg(not(target_arch = "wasm32"))]
1988pub fn fbbu_write_block_lease(lease_id: u128, lba: u64, data: &[u8; 512]) -> Result<()> {
1989 let status = mock::fbbu_write_block_lease_impl(lease_id, lba, data);
1990 match FabricError::from_status(status) {
1991 None => Ok(()),
1992 Some(e) => Err(e),
1993 }
1994}
1995
1996#[cfg(not(target_arch = "wasm32"))]
1998pub fn fbbu_read_block_lease(lease_id: u128, lba: u64, buf: &mut [u8; 512]) -> Result<()> {
1999 let status = mock::fbbu_read_block_lease_impl(lease_id, lba, buf);
2000 match FabricError::from_status(status) {
2001 None => Ok(()),
2002 Some(e) => Err(e),
2003 }
2004}
2005
2006#[cfg(not(target_arch = "wasm32"))]
2023pub fn tasklet_submit(
2024 wasm: &[u8],
2025 input: &[u8],
2026 fuel: u64,
2027 output_buf: &mut [u8],
2028) -> Result<(u64, usize)> {
2029 let (status, exit_code, output_len) = mock::tasklet_submit_impl(wasm, input, fuel, output_buf);
2030 match FabricError::from_status(status) {
2031 None => Ok((exit_code, output_len)),
2032 Some(e) => Err(e),
2033 }
2034}
2035
2036#[cfg(not(target_arch = "wasm32"))]
2042pub fn gpu_session_mem_alloc(lease_id: u128, size: u64) -> Result<u64> {
2043 let (status, handle) = mock::gpu_session_mem_alloc_impl(lease_id, size);
2044 session_status_to_result(status).map(|()| handle)
2048}
2049
2050#[cfg(not(target_arch = "wasm32"))]
2052pub fn gpu_session_mem_write(lease_id: u128, handle: u64, offset: u64, data: &[u8]) -> Result<()> {
2053 let status = mock::gpu_session_mem_write_impl(lease_id, handle, offset, data);
2054 session_status_to_result(status)
2055}
2056
2057#[cfg(not(target_arch = "wasm32"))]
2059pub fn gpu_session_mem_read(
2060 lease_id: u128,
2061 handle: u64,
2062 offset: u64,
2063 size: u32,
2064) -> Result<Vec<u8>> {
2065 let (status, data) = mock::gpu_session_mem_read_impl(lease_id, handle, offset, size);
2066 session_status_to_result(status).map(|()| data)
2067}
2068
2069#[cfg(not(target_arch = "wasm32"))]
2071pub fn gpu_session_mem_free(lease_id: u128, handle: u64) -> Result<()> {
2072 let status = mock::gpu_session_mem_free_impl(lease_id, handle);
2073 session_status_to_result(status)
2074}
2075
2076#[cfg(not(target_arch = "wasm32"))]
2078pub fn gpu_session_module_load(lease_id: u128, binary: &[u8]) -> Result<u64> {
2079 let (status, module_id) = mock::gpu_session_module_load_impl(lease_id, binary);
2080 session_status_to_result(status).map(|()| module_id)
2081}
2082
2083#[cfg(not(target_arch = "wasm32"))]
2085pub fn gpu_session_launch(
2086 lease_id: u128,
2087 module_id: u64,
2088 kernel_name: &str,
2089 grid_dim: [u32; 3],
2090 block_dim: [u32; 3],
2091 args: &[u8],
2092 arg_sizes: &[u32],
2093) -> Result<()> {
2094 let status = mock::gpu_session_launch_impl(
2095 lease_id,
2096 module_id,
2097 kernel_name,
2098 grid_dim,
2099 block_dim,
2100 args,
2101 arg_sizes,
2102 );
2103 session_status_to_result(status)
2104}
2105
2106#[cfg(not(target_arch = "wasm32"))]
2108pub fn gpu_session_sync(lease_id: u128) -> Result<()> {
2109 let status = mock::gpu_session_sync_impl(lease_id);
2110 session_status_to_result(status)
2111}
2112
2113#[cfg(not(target_arch = "wasm32"))]
2115pub fn gpu_session_module_unload(lease_id: u128, module_id: u64) -> Result<()> {
2116 let status = mock::gpu_session_module_unload_impl(lease_id, module_id);
2117 session_status_to_result(status)
2118}
2119
2120#[cfg(not(target_arch = "wasm32"))]
2127pub fn gpu_lease_alloc(resource_id: u128, lease_secs: u32) -> Result<u128> {
2128 let (status, lease_id) = mock::gpu_lease_alloc_impl(resource_id, lease_secs);
2129 match FabricError::from_status(status) {
2130 None => Ok(lease_id),
2131 Some(e) => Err(e),
2132 }
2133}
2134
2135#[cfg(not(target_arch = "wasm32"))]
2137pub fn gpu_lease_renew(lease_id: u128, duration_secs: u32) -> Result<()> {
2138 let status = mock::gpu_lease_renew_impl(lease_id, duration_secs);
2139 match FabricError::from_status(status) {
2140 None => Ok(()),
2141 Some(e) => Err(e),
2142 }
2143}
2144
2145#[cfg(not(target_arch = "wasm32"))]
2147pub fn gpu_lease_free(lease_id: u128) -> Result<()> {
2148 let status = mock::gpu_lease_free_impl(lease_id);
2149 match FabricError::from_status(status) {
2150 None => Ok(()),
2151 Some(e) => Err(e),
2152 }
2153}
2154
2155#[cfg(not(target_arch = "wasm32"))]
2158pub fn gpu_lease_query(lease_id: u128) -> Result<u32> {
2159 let (status, lease_status) = mock::gpu_lease_query_impl(lease_id);
2160 match FabricError::from_status(status) {
2161 None => Ok(lease_status),
2162 Some(e) => Err(e),
2163 }
2164}
2165
2166#[cfg(not(target_arch = "wasm32"))]
2174pub fn reset_mock() {
2175 mock::with_mock(|s| {
2176 *s = mock::MockState::default();
2177 });
2178}
2179
2180#[cfg(not(target_arch = "wasm32"))]
2185pub fn unix_time_secs() -> u64 {
2186 mock::with_mock(|s| s.now_unix_secs)
2187}
2188
2189#[cfg(target_arch = "wasm32")]
2191pub fn unix_time_secs() -> u64 {
2192 0
2193}
2194
2195#[cfg(not(target_arch = "wasm32"))]
2202pub fn mock_set_fbmu_arena_size(size: u64) {
2203 mock::with_mock(|s| {
2204 s.fbmu.arena_size = size;
2205 });
2206}
2207
2208#[cfg(not(target_arch = "wasm32"))]
2212pub fn mock_set_unix_time_secs(secs: u64) {
2213 mock::with_mock(|s| {
2214 s.now_unix_secs = secs;
2215 });
2216}
2217
2218#[cfg(not(target_arch = "wasm32"))]
2222pub fn mock_advance_time_secs(delta_secs: u64) {
2223 mock::with_mock(|s| {
2224 s.now_unix_secs = s.now_unix_secs.saturating_add(delta_secs);
2225 });
2226}
2227
2228#[cfg(not(target_arch = "wasm32"))]
2236pub fn mock_set_fbbu_num_blocks(n: u64) {
2237 mock::with_mock(|s| {
2238 s.fbbu.num_blocks = n;
2239 });
2240}
2241
2242#[cfg(not(target_arch = "wasm32"))]
2250pub fn mock_set_fbmu_hello_error(code: Option<i32>) {
2251 mock::with_mock(|s| {
2252 s.fbmu_hello_error = code;
2253 });
2254}
2255
2256#[cfg(not(target_arch = "wasm32"))]
2264pub fn mock_set_fbbu_hello_error(code: Option<i32>) {
2265 mock::with_mock(|s| {
2266 s.fbbu_hello_error = code;
2267 });
2268}
2269
2270#[cfg(not(target_arch = "wasm32"))]
2272pub fn mock_set_tasklet_result(exit_code: u64, output: &[u8]) {
2273 mock::with_mock(|s| {
2274 s.tasklet.exit_code = exit_code;
2275 s.tasklet.output = output.to_vec();
2276 });
2277}
2278
2279#[cfg(not(target_arch = "wasm32"))]
2281pub fn mock_set_tasklet_submit_error(code: Option<i32>) {
2282 mock::with_mock(|s| {
2283 s.tasklet_submit_error = code;
2284 });
2285}
2286
2287#[cfg(not(target_arch = "wasm32"))]
2301pub fn net_hello(min_bw: u64) -> Result<(alloc::string::String, u64)> {
2302 let (status, name, bw) = mock::net_hello_impl(min_bw);
2303 match FabricError::from_status(status) {
2304 None => Ok((name, bw)),
2305 Some(e) => Err(e),
2306 }
2307}
2308
2309#[cfg(not(target_arch = "wasm32"))]
2311pub fn mock_set_net_interface(name: &str, bandwidth: u64) {
2312 mock::with_mock(|s| {
2313 s.net.interface_name = alloc::string::String::from(name);
2314 s.net.bandwidth = bandwidth;
2315 });
2316}
2317
2318#[cfg(not(target_arch = "wasm32"))]
2320pub fn mock_set_net_hello_error(code: Option<i32>) {
2321 mock::with_mock(|s| {
2322 s.net_hello_error = code;
2323 });
2324}