1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9use bobcat_maths::U;
10
11pub type Address = [u8; 20];
12
13#[cfg(target_arch = "wasm32")]
14mod impls {
15 #[link(wasm_import_module = "vm_hooks")]
16 unsafe extern "C" {
17 pub(crate) fn pay_for_memory_grow(pages: u16);
18 pub(crate) fn write_result(d: *const u8, l: usize);
19 pub(crate) fn read_args(out: *mut u8);
20 pub(crate) fn msg_sender(addr: *mut u8);
21 pub(crate) fn msg_value(value: *mut u8);
22 pub(crate) fn msg_reentrant() -> bool;
23 }
24}
25
26#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
27mod impls {
28 use core::{ptr::copy_nonoverlapping, slice::from_raw_parts};
29
30 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
31
32 pub(crate) unsafe fn write_result(d: *const u8, l: usize) {
33 println!("{}", const_hex::encode(unsafe { from_raw_parts(d, l) }));
34 }
35
36 pub(crate) unsafe fn read_args(_out: *mut u8) {
37 unimplemented!("read from stdin separately. todo");
38 }
39
40 pub(crate) unsafe fn msg_sender(out: *mut u8) {
41 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
42 }
43
44 pub(crate) unsafe fn msg_value(out: *mut u8) {
45 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
46 }
47
48 pub(crate) unsafe fn msg_reentrant() -> bool {
49 false
50 }
51}
52
53#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
54mod impls {
55 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
56
57 pub(crate) unsafe fn write_result(_: *const u8, _: usize) {}
58
59 pub(crate) unsafe fn read_args(_out: *mut u8) {}
60
61 pub(crate) unsafe fn msg_sender(_: *mut u8) {}
62
63 pub(crate) unsafe fn msg_value(_: *mut u8) {}
64
65 pub(crate) unsafe fn msg_reentrant() -> bool {
66 false
67 }
68}
69
70#[unsafe(no_mangle)]
71pub unsafe fn mark_used() {
72 unsafe { impls::pay_for_memory_grow(0) }
73 panic!();
74}
75
76pub fn write_result(s: &[u8]) {
77 unsafe { impls::write_result(s.as_ptr(), s.len()) }
78}
79
80pub fn read_args<const CAP: usize>(len: usize) -> ([u8; CAP], usize) {
81 assert!(CAP >= len, "cap not enough");
82 let mut b = [0u8; CAP];
83 unsafe { impls::read_args(b.as_mut_ptr()) };
84 (b, len)
85}
86
87#[macro_export]
88macro_rules! read_args_safe {
89 ($len:expr, $max_len:expr) => {{
90 assert!($max_len >= $len);
91 $crate::read_args::<$max_len>($len).0
92 }};
93}
94
95#[cfg(feature = "alloc")]
96pub fn read_args_vec(len: usize) -> (Vec<u8>, usize) {
97 let mut b = Vec::with_capacity(len);
98 unsafe {
99 impls::read_args(b.as_mut_ptr());
100 b.set_len(len);
101 };
102 (b, len)
103}
104
105pub fn msg_sender() -> Address {
106 let mut b = [0u8; 20];
107 unsafe { impls::msg_sender(b.as_mut_ptr()) }
108 b
109}
110
111pub fn msg_value() -> U {
112 let mut b = [0u8; 32];
113 unsafe { impls::msg_value(b.as_mut_ptr()) }
114 U(b)
115}
116
117pub fn msg_reentrant() -> bool {
118 unsafe { impls::msg_reentrant() }
119}