1use std::ffi::c_void;
8use std::mem::ManuallyDrop;
9use std::ops::{Deref, DerefMut};
10use std::os::raw::c_char;
11
12use crate::Interpreter;
13use crate::ObjectType;
14use crate::RawObject;
15
16pub(crate) static mut ALLOC: Option<extern "C" fn(usize) -> *mut c_void> = None;
17pub(crate) static mut REALLOC: Option<extern "C" fn(*mut c_void, usize) -> *mut c_void> = None;
18pub(crate) static mut FREE: Option<extern "C" fn(*mut c_void)> = None;
19
20pub(crate) static mut NEW_OBJ: Option<extern "C" fn() -> *mut RawObject> = None;
21pub(crate) static mut DUPLICATE_OBJ: Option<extern "C" fn(*mut RawObject) -> *mut RawObject> = None;
22pub(crate) static mut INCR_REF_COUNT: Option<extern "C" fn(*mut RawObject)> = None;
23pub(crate) static mut DECR_REF_COUNT: Option<extern "C" fn(*mut RawObject)> = None;
24pub(crate) static mut IS_SHARED: Option<extern "C" fn(*mut RawObject) -> i32> = None;
25pub(crate) static mut INVALIDATE_STRING_REP: Option<extern "C" fn(*mut RawObject)> = None;
26pub(crate) static mut GET_STRING: Option<extern "C" fn(*mut RawObject) -> *mut c_char> = None;
27
28pub(crate) static mut GET_OBJ_TYPE: Option<extern "C" fn(*const c_char) -> *const ObjectType> =
29 None;
30pub(crate) static mut CONVERT_TO_TYPE: Option<
31 extern "C" fn(*const Interpreter, *mut RawObject, *const ObjectType) -> i32,
32> = None;
33
34pub(crate) static mut NEW_STRING_OBJ: Option<
35 extern "C" fn(*const c_char, usize) -> *mut RawObject,
36> = None;
37
38pub(crate) static mut SET_STRING_OBJ: Option<extern "C" fn(*mut RawObject, *const c_char, usize)> =
39 None;
40
41pub struct TclBuf {
50 ptr: *mut u8,
51 len: usize,
53}
54
55impl TclBuf {
56 pub(crate) unsafe fn from_raw_parts(ptr: *mut u8, len: usize) -> Self {
64 Self { ptr, len }
65 }
66
67 pub fn len(&self) -> usize {
69 self.len
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.len == 0
75 }
76
77 pub fn into_raw_parts(self) -> (*mut c_char, usize) {
85 let md = ManuallyDrop::new(self);
86 (md.ptr as *mut c_char, md.len)
87 }
88}
89
90impl Drop for TclBuf {
91 fn drop(&mut self) {
92 unsafe { FREE.expect("module must have been initialized")(self.ptr as *mut c_void) }
93 }
94}
95
96impl Deref for TclBuf {
97 type Target = [u8];
98 fn deref(&self) -> &[u8] {
99 unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
100 }
101}
102
103impl DerefMut for TclBuf {
104 fn deref_mut(&mut self) -> &mut [u8] {
105 unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }
106 }
107}
108
109unsafe impl Send for TclBuf {}
112
113pub fn tcl_string(rust_str: &str) -> TclBuf {
121 let alloc_len = rust_str.len() + 1; unsafe {
123 let ptr = ALLOC.expect("module not initialized")(alloc_len) as *mut u8;
124 let slice = std::slice::from_raw_parts_mut(ptr, alloc_len);
125 slice[..rust_str.len()].copy_from_slice(rust_str.as_bytes());
126 *slice.last_mut().expect("alloc_len is always >= 1") = 0;
127 TclBuf::from_raw_parts(ptr, rust_str.len())
128 }
129}