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
64use crate::{
65    registry::Registry,
66    types::{enum_type::Enum, struct_type::Struct},
67};
68use serde::{Deserialize, Serialize};
69
70#[derive(
71    Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
72)]
73pub enum Visibility {
74    Private,
75    Module,
76    #[default]
77    Public,
78}
79
80impl Visibility {
81    pub fn is_visible(self, scope: Self) -> bool {
82        self >= scope
83    }
84
85    pub fn is_public(&self) -> bool {
86        *self == Visibility::Public
87    }
88
89    pub fn is_module(&self) -> bool {
90        *self == Visibility::Module
91    }
92
93    pub fn is_private(&self) -> bool {
94        *self == Visibility::Private
95    }
96}
97
98pub trait IntuicioStruct {
99    fn define_struct(registry: &Registry) -> Struct;
100}
101
102pub trait IntuicioEnum {
103    fn define_enum(registry: &Registry) -> Enum;
104}
105
106#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
107#[repr(C)]
108pub struct IntuicioVersion {
109    major: usize,
110    minor: usize,
111    patch: usize,
112}
113
114impl IntuicioVersion {
115    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
116        Self {
117            major,
118            minor,
119            patch,
120        }
121    }
122
123    pub fn major(&self) -> usize {
124        self.major
125    }
126
127    pub fn minor(&self) -> usize {
128        self.minor
129    }
130
131    pub fn patch(&self) -> usize {
132        self.patch
133    }
134
135    pub fn is_compatible(&self, other: &Self) -> bool {
136        self.major == other.major && self.minor == other.minor
137    }
138}
139
140impl std::fmt::Display for IntuicioVersion {
141    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
143    }
144}
145
146impl std::fmt::Debug for IntuicioVersion {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        f.debug_struct("IntuicioVersion")
149            .field("major", &self.major)
150            .field("minor", &self.minor)
151            .field("patch", &self.patch)
152            .finish()
153    }
154}
155
156#[macro_export]
157macro_rules! crate_version {
158    () => {{
159        let major = option_env!("CARGO_PKG_VERSION_MAJOR")
160            .unwrap_or("0")
161            .parse::<usize>()
162            .unwrap();
163        let minor = option_env!("CARGO_PKG_VERSION_MINOR")
164            .unwrap_or("0")
165            .parse::<usize>()
166            .unwrap();
167        let patch = option_env!("CARGO_PKG_VERSION_PATCH")
168            .unwrap_or("0")
169            .parse::<usize>()
170            .unwrap();
171        $crate::IntuicioVersion::new(major, minor, patch)
172    }};
173}
174
175pub fn core_version() -> IntuicioVersion {
176    crate_version!()
177}
178
179#[cfg(test)]
180mod tests {
181    use crate::Visibility;
182
183    #[test]
184    fn test_visibility() {
185        assert!(Visibility::Private.is_visible(Visibility::Private));
186        assert!(!Visibility::Private.is_visible(Visibility::Module));
187        assert!(!Visibility::Private.is_visible(Visibility::Public));
188        assert!(Visibility::Module.is_visible(Visibility::Private));
189        assert!(Visibility::Module.is_visible(Visibility::Module));
190        assert!(!Visibility::Module.is_visible(Visibility::Public));
191        assert!(Visibility::Public.is_visible(Visibility::Private));
192        assert!(Visibility::Public.is_visible(Visibility::Module));
193        assert!(Visibility::Public.is_visible(Visibility::Public));
194    }
195
196    #[test]
197    fn test_offset_of_enum() {
198        #[allow(dead_code)]
199        #[repr(u8)]
200        enum Foo {
201            A,
202            B(usize),
203            C(u8, u16),
204            D { a: u32, b: u64 },
205        }
206
207        assert_eq!(__internal__offset_of_enum__!(Foo::B[v] => v => 1), 8);
208        assert_eq!(__internal__offset_of_enum__!(Foo::B(0) => 1), 8);
209        assert_eq!(__internal__offset_of_enum__!(Foo::C[a, b] => a => 2), 1);
210        assert_eq!(__internal__offset_of_enum__!(Foo::C[a, b] => b => 2), 2);
211        assert_eq!(__internal__offset_of_enum__!(Foo::C(0) => 2), 1);
212        assert_eq!(__internal__offset_of_enum__!(Foo::C(1) => 2), 2);
213        assert_eq!(__internal__offset_of_enum__!(Foo::D { a } => 3), 4);
214        assert_eq!(__internal__offset_of_enum__!(Foo::D { b } => 3), 8);
215    }
216}