Skip to main content

interstice_sdk/
macros.rs

1use interstice_abi::{
2    Authority, ModuleDependency, ModuleVisibility, NodeDependency, encode, pack_ptr_len,
3};
4
5#[macro_export]
6macro_rules! interstice_module {
7    () => {
8        interstice_module!(visibility: Private, authorities: []);
9    };
10
11    (visibility: $vis:ident) => {
12        interstice_module!(visibility: $vis, authorities: []);
13    };
14
15    (authorities: [$($auth:ident),* $(,)?]) => {
16        interstice_module!(visibility: Private, authorities: [$($auth),*]);
17    };
18
19    (visibility: $vis:ident, authorities: [$($auth:ident),* $(,)?]) => {
20        $(
21            interstice_module!(@impl_authority $auth);
22        )*
23
24        // Global imports (for traits used in macros)
25        use std::str::FromStr;
26        // Use wee_alloc as the global allocator.
27
28        #[global_allocator]
29        static ALLOC: interstice_sdk::wee_alloc::WeeAlloc =
30            interstice_sdk::wee_alloc::WeeAlloc::INIT;
31
32        #[unsafe(no_mangle)]
33        pub extern "C" fn alloc(size: i32) -> i32 {
34            let layout = std::alloc::Layout::from_size_align(size as usize, 8).unwrap();
35            unsafe { std::alloc::alloc(layout) as i32 }
36        }
37
38        #[unsafe(no_mangle)]
39        pub extern "C" fn dealloc(ptr: i32, size: i32) {
40            let layout = std::alloc::Layout::from_size_align(size as usize, 8).unwrap();
41            unsafe { std::alloc::dealloc(ptr as *mut u8, layout) }
42        }
43
44        // Panic hook to log panics to host
45        #[$crate::init]
46        fn interstice_init() {
47            std::panic::set_hook(Box::new(|info| {
48                let msg = if let Some(s) = info.payload().downcast_ref::<&str>() {
49                    *s
50                } else if let Some(s) = info.payload().downcast_ref::<String>() {
51                    s.as_str()
52                } else {
53                    "panic occurred"
54                };
55
56                // send to host
57                interstice_sdk::host_calls::log(&format!("Panic Error: {}", msg));
58            }));
59        }
60
61        // BINDINGS
62        pub mod bindings {
63            include!(concat!(env!("OUT_DIR"), "/interstice_bindings.rs"));
64        }
65
66        // Module Schema Description
67
68        const __INTERSTICE_MODULE_NAME: &str = env!("CARGO_PKG_NAME");
69        const __INTERSTICE_MODULE_VERSION: &str = env!("CARGO_PKG_VERSION");
70        const __INTERSTICE_VISIBILITY: ModuleVisibility = ModuleVisibility::$vis;
71        const __INTERSTICE_AUTHORITIES: &[interstice_abi::Authority] = &[
72            $(interstice_abi::Authority::$auth),*
73        ];
74
75        #[unsafe(no_mangle)]
76        pub extern "C" fn interstice_describe() -> i64 {
77            interstice_sdk::macros::describe_module(
78                __INTERSTICE_MODULE_NAME,
79                __INTERSTICE_MODULE_VERSION,
80                __INTERSTICE_VISIBILITY,
81                __INTERSTICE_AUTHORITIES,
82                bindings::__GET_INTERSTICE_MODULE_DEPENDENCIES(),
83                bindings::__GET_INTERSTICE_NODE_DEPENDENCIES()
84            )
85        }
86
87    };
88    // Authorites calls
89
90    (@impl_authority Input) => {
91    };
92
93    (@impl_authority Gpu) => {
94        pub trait GpuExt {
95            fn gpu(&self) -> Gpu;
96        }
97
98        impl GpuExt for interstice_sdk::ReducerContext {
99            fn gpu(&self) -> interstice_sdk::Gpu {
100                interstice_sdk::Gpu
101            }
102        }
103    };
104
105    (@impl_authority File) => {
106        pub trait FileExt {
107            fn file(&self) -> File;
108        }
109
110        impl FileExt for interstice_sdk::ReducerContext {
111            fn file(&self) -> interstice_sdk::File {
112                interstice_sdk::File
113            }
114        }
115    };
116
117    (@impl_authority Module) => {
118        pub trait ModuleExt {
119            fn module(&self) -> ModuleAuthority;
120        }
121
122        impl ModuleExt for interstice_sdk::ReducerContext {
123            fn module(&self) -> interstice_sdk::ModuleAuthority {
124                interstice_sdk::ModuleAuthority
125            }
126        }
127    };
128}
129
130pub fn describe_module(
131    name: &str,
132    version: &str,
133    visibility: ModuleVisibility,
134    authorities: &'static [Authority],
135    module_dependencies: Vec<ModuleDependency>,
136    node_dependencies: Vec<NodeDependency>,
137) -> i64 {
138    let reducers = interstice_sdk_core::registry::collect_reducers();
139    let queries = interstice_sdk_core::registry::collect_queries();
140    let tables = interstice_sdk_core::registry::collect_tables();
141    let subscriptions = interstice_sdk_core::registry::collect_subscriptions();
142    let type_definitions = interstice_sdk_core::registry::collect_type_definitions();
143
144    let schema = interstice_abi::ModuleSchema {
145        abi_version: interstice_abi::ABI_VERSION,
146        name: name.to_string(),
147        version: version.into(),
148        visibility,
149        reducers,
150        queries,
151        tables,
152        subscriptions,
153        type_definitions,
154        authorities: authorities.to_vec(),
155        module_dependencies,
156        node_dependencies,
157    };
158
159    let bytes = encode(&schema).unwrap();
160    let len = bytes.len() as i32;
161    let ptr = Box::into_raw(bytes.into_boxed_slice()) as *mut u8 as i32;
162    return pack_ptr_len(ptr, len);
163}