intuicio_core/
lib.rs

1pub mod context;
2pub mod function;
3pub mod host;
4pub mod meta;
5pub mod object;
6pub mod registry;
7pub mod script;
8pub mod transformer;
9pub mod types;
10pub mod utils;
11
12pub use memoffset::offset_of as __internal__offset_of__;
13
14/// Assumes `repr(u8)` enums only.
15#[macro_export]
16macro_rules! __internal__offset_of_enum__ {
17    ($type:tt :: $variant:ident [ $( $field:ident ),* ] => $used_field:ident => $discriminant:literal) => {{
18        let mut data = std::mem::MaybeUninit::<$type>::uninit();
19        let ptr = data.as_mut_ptr().cast::<u8>();
20        #[allow(clippy::macro_metavars_in_unsafe)]
21        unsafe {
22            ptr.write($discriminant);
23            #[allow(unused_variables)]
24            match data.assume_init_ref() {
25                $type::$variant( $( $field ),* ) => {
26                    ($used_field as *const _ as *const u8).offset_from(ptr) as usize
27                }
28                _ => unreachable!(),
29            }
30        }
31    }};
32    ($type:tt :: $variant:ident ( $index:tt ) => $discriminant:literal) => {{
33        let mut data = std::mem::MaybeUninit::<$type>::uninit();
34        let ptr = data.as_mut_ptr().cast::<u8>();
35        #[allow(clippy::macro_metavars_in_unsafe)]
36        unsafe {
37            ptr.write($discriminant);
38            #[allow(unused_variables)]
39            match data.assume_init_ref() {
40                $type::$variant {
41                    $index: __value__, ..
42                } => (__value__ as *const _ as *const u8).offset_from(ptr) as usize,
43                _ => unreachable!(),
44            }
45        }
46    }};
47    ($type:tt :: $variant:ident { $field:ident } => $discriminant:literal) => {{
48        let mut data = std::mem::MaybeUninit::<$type>::uninit();
49        let ptr = data.as_mut_ptr().cast::<u8>();
50        #[allow(clippy::macro_metavars_in_unsafe)]
51        unsafe {
52            ptr.write($discriminant);
53            #[allow(unused_variables)]
54            match data.assume_init_ref() {
55                $type::$variant { $field, .. } => {
56                    ($field as *const _ as *const u8).offset_from(ptr) as usize
57                }
58                _ => unreachable!(),
59            }
60        }
61    }};
62}
63
64pub mod prelude {
65    pub use crate::{
66        IntuicioEnum, IntuicioStruct, IntuicioVersion, Visibility,
67        context::*,
68        function::*,
69        host::*,
70        object::*,
71        registry::*,
72        script::*,
73        transformer::*,
74        types::{enum_type::*, struct_type::*, *},
75    };
76    pub use crate::{
77        define_function, define_native_enum, define_native_struct, define_runtime_enum,
78        define_runtime_struct, function_signature,
79    };
80}
81
82use crate::{
83    registry::Registry,
84    types::{enum_type::Enum, struct_type::Struct},
85};
86use serde::{Deserialize, Serialize};
87
88#[derive(
89    Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
90)]
91pub enum Visibility {
92    Private,
93    Module,
94    #[default]
95    Public,
96}
97
98impl Visibility {
99    pub fn is_visible(self, scope: Self) -> bool {
100        self >= scope
101    }
102
103    pub fn is_public(&self) -> bool {
104        *self == Visibility::Public
105    }
106
107    pub fn is_module(&self) -> bool {
108        *self == Visibility::Module
109    }
110
111    pub fn is_private(&self) -> bool {
112        *self == Visibility::Private
113    }
114}
115
116pub trait IntuicioStruct {
117    fn define_struct(registry: &Registry) -> Struct;
118}
119
120pub trait IntuicioEnum {
121    fn define_enum(registry: &Registry) -> Enum;
122}
123
124#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
125#[repr(C)]
126pub struct IntuicioVersion {
127    major: usize,
128    minor: usize,
129    patch: usize,
130}
131
132impl IntuicioVersion {
133    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
134        Self {
135            major,
136            minor,
137            patch,
138        }
139    }
140
141    pub fn major(&self) -> usize {
142        self.major
143    }
144
145    pub fn minor(&self) -> usize {
146        self.minor
147    }
148
149    pub fn patch(&self) -> usize {
150        self.patch
151    }
152
153    pub fn is_compatible(&self, other: &Self) -> bool {
154        self.major == other.major && self.minor == other.minor
155    }
156}
157
158impl std::fmt::Display for IntuicioVersion {
159    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
161    }
162}
163
164impl std::fmt::Debug for IntuicioVersion {
165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166        f.debug_struct("IntuicioVersion")
167            .field("major", &self.major)
168            .field("minor", &self.minor)
169            .field("patch", &self.patch)
170            .finish()
171    }
172}
173
174#[macro_export]
175macro_rules! crate_version {
176    () => {{
177        let major = env!("CARGO_PKG_VERSION_MAJOR", "0")
178            .parse::<usize>()
179            .unwrap();
180        let minor = env!("CARGO_PKG_VERSION_MINOR", "0")
181            .parse::<usize>()
182            .unwrap();
183        let patch = env!("CARGO_PKG_VERSION_PATCH", "0")
184            .parse::<usize>()
185            .unwrap();
186        $crate::IntuicioVersion::new(major, minor, patch)
187    }};
188}
189
190pub fn core_version() -> IntuicioVersion {
191    crate_version!()
192}
193
194#[cfg(test)]
195mod tests {
196    use crate::Visibility;
197
198    #[test]
199    fn test_visibility() {
200        assert!(Visibility::Private.is_visible(Visibility::Private));
201        assert!(!Visibility::Private.is_visible(Visibility::Module));
202        assert!(!Visibility::Private.is_visible(Visibility::Public));
203        assert!(Visibility::Module.is_visible(Visibility::Private));
204        assert!(Visibility::Module.is_visible(Visibility::Module));
205        assert!(!Visibility::Module.is_visible(Visibility::Public));
206        assert!(Visibility::Public.is_visible(Visibility::Private));
207        assert!(Visibility::Public.is_visible(Visibility::Module));
208        assert!(Visibility::Public.is_visible(Visibility::Public));
209    }
210
211    #[test]
212    fn test_offset_of_enum() {
213        #[allow(dead_code)]
214        #[repr(u8)]
215        enum Foo {
216            A,
217            B(usize),
218            C(u8, u16),
219            D { a: u32, b: u64 },
220        }
221
222        assert_eq!(__internal__offset_of_enum__!(Foo::B[v] => v => 1), 8);
223        assert_eq!(__internal__offset_of_enum__!(Foo::B(0) => 1), 8);
224        assert_eq!(__internal__offset_of_enum__!(Foo::C[a, b] => a => 2), 1);
225        assert_eq!(__internal__offset_of_enum__!(Foo::C[a, b] => b => 2), 2);
226        assert_eq!(__internal__offset_of_enum__!(Foo::C(0) => 2), 1);
227        assert_eq!(__internal__offset_of_enum__!(Foo::C(1) => 2), 2);
228        assert_eq!(__internal__offset_of_enum__!(Foo::D { a } => 3), 4);
229        assert_eq!(__internal__offset_of_enum__!(Foo::D { b } => 3), 8);
230    }
231}