artichoke_backend/extn/core/symbol/
ffi.rs

1use std::ffi::{CStr, c_char};
2use std::ptr;
3use std::slice;
4
5use crate::extn::core::symbol::Symbol;
6use crate::extn::prelude::*;
7
8// ```c
9// MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t);
10// ```
11#[unsafe(no_mangle)]
12unsafe extern "C-unwind" fn mrb_intern(mrb: *mut sys::mrb_state, name: *const c_char, len: usize) -> sys::mrb_sym {
13    let bytes = slice::from_raw_parts(name.cast::<u8>(), len);
14    let bytes = bytes.to_vec();
15    unwrap_interpreter!(mrb, to => guard, or_else = 0);
16    let sym = guard.intern_bytes(bytes);
17    sym.unwrap_or_default()
18}
19
20// ```c
21// MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t);
22// ```
23#[unsafe(no_mangle)]
24unsafe extern "C-unwind" fn mrb_intern_static(
25    mrb: *mut sys::mrb_state,
26    name: *const c_char,
27    len: usize,
28) -> sys::mrb_sym {
29    let bytes = slice::from_raw_parts::<'static, _>(name.cast::<u8>(), len);
30    unwrap_interpreter!(mrb, to => guard, or_else = 0);
31    let sym = guard.intern_bytes(bytes);
32    sym.unwrap_or_default()
33}
34
35// ```c
36// MRB_API mrb_sym mrb_intern_cstr(mrb_state *mrb, const char* str);
37// ```
38#[unsafe(no_mangle)]
39unsafe extern "C-unwind" fn mrb_intern_cstr(mrb: *mut sys::mrb_state, name: *const c_char) -> sys::mrb_sym {
40    let string = CStr::from_ptr(name);
41    let bytes = string.to_bytes_with_nul().to_vec();
42    unwrap_interpreter!(mrb, to => guard, or_else = 0);
43    let sym = guard.intern_bytes_with_trailing_nul(bytes);
44    sym.unwrap_or_default()
45}
46
47// ```c
48// MRB_API mrb_sym mrb_intern_str(mrb_state*,mrb_value);
49// ```
50#[unsafe(no_mangle)]
51unsafe extern "C-unwind" fn mrb_intern_str(mrb: *mut sys::mrb_state, name: sys::mrb_value) -> sys::mrb_sym {
52    unwrap_interpreter!(mrb, to => guard, or_else = 0);
53    let name = Value::from(name);
54    let Ok(bytes) = name.try_convert_into_mut::<Vec<u8>>(&mut guard) else {
55        return 0;
56    };
57    let sym = guard.intern_bytes(bytes);
58    sym.unwrap_or_default()
59}
60
61/* `mrb_intern_check` series functions returns 0 if the symbol is not defined */
62
63// ```c
64// MRB_API mrb_sym mrb_intern_check(mrb_state*,const char*,size_t);
65// ```
66#[unsafe(no_mangle)]
67unsafe extern "C-unwind" fn mrb_intern_check(
68    mrb: *mut sys::mrb_state,
69    name: *const c_char,
70    len: usize,
71) -> sys::mrb_sym {
72    let bytes = slice::from_raw_parts(name.cast::<u8>(), len);
73    unwrap_interpreter!(mrb, to => guard, or_else = 0);
74    let Ok(Some(sym)) = guard.check_interned_bytes(bytes) else {
75        return 0;
76    };
77    sym
78}
79
80// ```c
81// MRB_API mrb_sym mrb_intern_check_cstr(mrb_state*,const char*);
82// ```
83#[unsafe(no_mangle)]
84unsafe extern "C-unwind" fn mrb_intern_check_cstr(mrb: *mut sys::mrb_state, name: *const c_char) -> sys::mrb_sym {
85    let string = CStr::from_ptr(name);
86    let bytes = string.to_bytes_with_nul();
87    unwrap_interpreter!(mrb, to => guard, or_else = 0);
88    let Ok(Some(sym)) = guard.check_interned_bytes_with_trailing_nul(bytes) else {
89        return 0;
90    };
91    sym
92}
93
94// ```c
95// MRB_API mrb_sym mrb_intern_check_str(mrb_state*,mrb_value);
96// ```
97#[unsafe(no_mangle)]
98unsafe extern "C-unwind" fn mrb_intern_check_str(mrb: *mut sys::mrb_state, name: sys::mrb_value) -> sys::mrb_sym {
99    unwrap_interpreter!(mrb, to => guard, or_else = 0);
100    let name = Value::from(name);
101    let Ok(bytes) = name.try_convert_into_mut::<&[u8]>(&mut guard) else {
102        return 0;
103    };
104    let Ok(Some(sym)) = guard.check_interned_bytes(bytes) else {
105        return 0;
106    };
107    sym
108}
109
110// `mrb_check_intern` series functions returns `nil` if the symbol is not
111// defined; otherwise returns `mrb_value`.
112
113// ```c
114// MRB_API mrb_value mrb_check_intern(mrb_state*,const char*,size_t);
115// ```
116#[unsafe(no_mangle)]
117unsafe extern "C-unwind" fn mrb_check_intern(
118    mrb: *mut sys::mrb_state,
119    name: *const c_char,
120    len: usize,
121) -> sys::mrb_value {
122    let bytes = slice::from_raw_parts(name.cast::<u8>(), len);
123    unwrap_interpreter!(mrb, to => guard);
124    let Ok(Some(sym)) = guard.check_interned_bytes(bytes) else {
125        return Value::nil().inner();
126    };
127    Symbol::alloc_value(sym.into(), &mut guard).unwrap_or_default().inner()
128}
129
130// ```c
131// MRB_API mrb_value mrb_check_intern_cstr(mrb_state*,const char*);
132// ```
133#[unsafe(no_mangle)]
134unsafe extern "C-unwind" fn mrb_check_intern_cstr(mrb: *mut sys::mrb_state, name: *const c_char) -> sys::mrb_value {
135    let string = CStr::from_ptr(name);
136    let bytes = string.to_bytes_with_nul();
137    unwrap_interpreter!(mrb, to => guard);
138    let Ok(Some(sym)) = guard.check_interned_bytes_with_trailing_nul(bytes) else {
139        return Value::nil().inner();
140    };
141    Symbol::alloc_value(sym.into(), &mut guard).unwrap_or_default().inner()
142}
143
144// ```c
145// MRB_API mrb_value mrb_check_intern_str(mrb_state*,mrb_value);
146// ```
147#[unsafe(no_mangle)]
148unsafe extern "C-unwind" fn mrb_check_intern_str(mrb: *mut sys::mrb_state, name: sys::mrb_value) -> sys::mrb_value {
149    unwrap_interpreter!(mrb, to => guard);
150    let name = Value::from(name);
151    let Ok(bytes) = name.try_convert_into_mut::<&[u8]>(&mut guard) else {
152        return Value::nil().inner();
153    };
154    let Ok(Some(sym)) = guard.check_interned_bytes(bytes) else {
155        return Value::nil().inner();
156    };
157    Symbol::alloc_value(sym.into(), &mut guard).unwrap_or_default().inner()
158}
159
160// ```c
161// MRB_API const char *mrb_sym_name(mrb_state*,mrb_sym);
162// ```
163#[unsafe(no_mangle)]
164unsafe extern "C-unwind" fn mrb_sym_name(mrb: *mut sys::mrb_state, sym: sys::mrb_sym) -> *const c_char {
165    unwrap_interpreter!(mrb, to => guard, or_else = ptr::null());
166    let Ok(Some(bytes)) = guard.lookup_symbol_with_trailing_nul(sym) else {
167        return ptr::null();
168    };
169    bytes.as_ptr().cast::<c_char>()
170}
171
172// ```c
173// MRB_API const char *mrb_sym_name_len(mrb_state*,mrb_sym,mrb_int*);
174// ```
175#[unsafe(no_mangle)]
176unsafe extern "C-unwind" fn mrb_sym_name_len(
177    mrb: *mut sys::mrb_state,
178    sym: sys::mrb_sym,
179    lenp: *mut sys::mrb_int,
180) -> *const c_char {
181    if !lenp.is_null() {
182        ptr::write(lenp, 0);
183    }
184    unwrap_interpreter!(mrb, to => guard, or_else = ptr::null());
185    let Ok(Some(bytes)) = guard.lookup_symbol(sym) else {
186        return ptr::null();
187    };
188    if !lenp.is_null() {
189        let Ok(len) = sys::mrb_int::try_from(bytes.len()) else {
190            return ptr::null();
191        };
192        ptr::write(lenp, len);
193    }
194    bytes.as_ptr().cast()
195}
196
197// ```c
198// MRB_API const char *mrb_sym_dump(mrb_state*,mrb_sym);
199// ```
200#[unsafe(no_mangle)]
201unsafe extern "C-unwind" fn mrb_sym_dump(mrb: *mut sys::mrb_state, sym: sys::mrb_sym) -> *const c_char {
202    unwrap_interpreter!(mrb, to => guard, or_else = ptr::null());
203    let Ok(Some(bytes)) = guard.lookup_symbol(sym) else {
204        return ptr::null();
205    };
206    let bytes = bytes.to_vec();
207    // Allocate a buffer with the lifetime of the interpreter and return
208    // a pointer to it.
209    let Ok(string) = guard.try_convert_mut(bytes) else {
210        return ptr::null();
211    };
212    let Ok(bytes) = string.try_convert_into_mut::<&[u8]>(&mut guard) else {
213        return ptr::null();
214    };
215    bytes.as_ptr().cast()
216}
217
218// ```c
219// MRB_API mrb_value mrb_sym_str(mrb_state*,mrb_sym);
220// ```
221#[unsafe(no_mangle)]
222unsafe extern "C-unwind" fn mrb_sym_str(mrb: *mut sys::mrb_state, sym: sys::mrb_sym) -> sys::mrb_value {
223    unwrap_interpreter!(mrb, to => guard);
224
225    let value = if let Ok(Some(bytes)) = guard.lookup_symbol(sym) {
226        let bytes = bytes.to_vec();
227        guard.try_convert_mut(bytes)
228    } else {
229        guard.try_convert_mut("")
230    };
231    value.unwrap_or_default().inner()
232}
233
234// ```c
235// void mrb_init_symtbl(mrb_state*);
236// ```
237#[unsafe(no_mangle)]
238unsafe extern "C-unwind" fn mrb_init_symtbl(mrb: *mut sys::mrb_state) {
239    // The symbol table is initialized before the call to `mrb_open_allocf` in
240    // `crate::interpreter::interpreter`. This function is intended to be called
241    // during the initialization of the `mrb_state`.
242    let _ = mrb;
243}
244
245// ```c
246// void mrb_free_symtbl(mrb_state *mrb);
247// ```
248#[unsafe(no_mangle)]
249unsafe extern "C-unwind" fn mrb_free_symtbl(mrb: *mut sys::mrb_state) {
250    // The symbol table is freed when the Rust `State` is freed.
251    let _ = mrb;
252}