bobcat_entry/
lib.rs

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}