Skip to content

Commit 1c688a4

Browse files
committed
initial tcl crate
1 parent f65b463 commit 1c688a4

File tree

5 files changed

+296
-0
lines changed

5 files changed

+296
-0
lines changed

tcl/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "tcl"
3+
edition.workspace = true
4+
authors.workspace = true
5+
readme.workspace = true
6+
repository.workspace = true
7+
version.workspace = true
8+
license.workspace = true
9+
include.workspace = true
10+
rust-version.workspace = true
11+
12+
[dependencies]
13+
tcl-sys = { version = "0.3", path = "../tcl-sys" }

tcl/src/interp.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use std::ptr::NonNull;
2+
use crate::Obj;
3+
4+
pub struct Interp(pub(crate) NonNull<tcl_sys::Tcl_Interp>);
5+
6+
impl Interp {
7+
pub fn new() -> Self {
8+
let interp = unsafe { tcl_sys::Tcl_CreateInterp() };
9+
unsafe {
10+
Interp::from_raw(interp)
11+
}
12+
}
13+
14+
pub unsafe fn from_raw(interp: *mut tcl_sys::Tcl_Interp) -> Self {
15+
Interp(NonNull::new(interp).unwrap())
16+
}
17+
18+
pub fn create_slave(&mut self, name: &str, is_safe: i32) -> Self {
19+
let name = std::ffi::CString::new(name).unwrap();
20+
let interp = unsafe {
21+
tcl_sys::Tcl_CreateSlave(self.0.as_ptr(), name.as_ptr(), is_safe as _)
22+
};
23+
unsafe {
24+
Interp::from_raw(interp)
25+
}
26+
}
27+
28+
pub fn get_slave(&mut self, name: &str) -> Self {
29+
let name = std::ffi::CString::new(name).unwrap();
30+
let interp = unsafe {
31+
tcl_sys::Tcl_GetSlave(self.0.as_ptr(), name.as_ptr())
32+
};
33+
unsafe {
34+
Interp::from_raw(interp)
35+
}
36+
}
37+
38+
pub unsafe fn get_obj_result(&self) -> Obj {
39+
Obj::from_raw(tcl_sys::Tcl_GetObjResult(self.0.as_ptr()))
40+
}
41+
42+
pub unsafe fn eval(&self, script: &str) -> i32 {
43+
let script = std::ffi::CString::new(script).unwrap();
44+
tcl_sys::Tcl_Eval(self.0.as_ptr(), script.as_ptr()) as i32
45+
}
46+
47+
pub unsafe fn eval_ex(&self, script: &str, num_bytes: i32, flags: i32) -> i32 {
48+
let script = std::ffi::CString::new(script).unwrap();
49+
tcl_sys::Tcl_EvalEx(self.0.as_ptr(), script.as_ptr(), num_bytes, flags) as i32
50+
}
51+
52+
pub unsafe fn eval_obj(&self, obj: Obj) -> i32 {
53+
tcl_sys::Tcl_EvalObj(self.0.as_ptr(), obj.0.as_ptr()) as i32
54+
}
55+
56+
pub unsafe fn eval_file(&self, filename: &str) -> i32 {
57+
let filename = std::ffi::CString::new(filename).unwrap();
58+
tcl_sys::Tcl_EvalFile(self.0.as_ptr(), filename.as_ptr()) as i32
59+
}
60+
}
61+
62+
impl Drop for Interp {
63+
fn drop(&mut self) {
64+
unsafe {
65+
tcl_sys::Tcl_DeleteInterp(self.0.as_ptr());
66+
}
67+
}
68+
}

tcl/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
mod interp;
2+
mod obj;
3+
mod time;
4+
5+
pub use interp::Interp;
6+
pub use obj::Obj;
7+
pub use time::Time;
8+
9+
pub fn get_errno() -> i32 {
10+
unsafe {
11+
tcl_sys::Tcl_GetErrno() as _
12+
}
13+
}
14+
15+
pub fn set_errno(errno: i32) {
16+
unsafe {
17+
tcl_sys::Tcl_SetErrno(errno as _);
18+
}
19+
}

tcl/src/obj.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
use std::ptr::NonNull;
2+
3+
pub struct Obj(pub(crate) NonNull<tcl_sys::Tcl_Obj>);
4+
5+
impl Obj {
6+
pub fn new() -> Self {
7+
let obj = unsafe { tcl_sys::Tcl_NewObj() };
8+
unsafe {
9+
Self::from_raw(obj)
10+
}
11+
}
12+
13+
pub unsafe fn from_raw(obj: *mut tcl_sys::Tcl_Obj) -> Self {
14+
Obj(NonNull::new(obj).expect("Failed to create Tcl_Obj from raw pointer"))
15+
}
16+
17+
pub fn from_string(string: &str) -> Self {
18+
let c_str = std::ffi::CString::new(string).expect("Failed to create CString");
19+
let obj = unsafe { tcl_sys::Tcl_NewStringObj(c_str.as_ptr(), c_str.as_bytes().len() as i32) };
20+
unsafe {
21+
Self::from_raw(obj)
22+
}
23+
}
24+
25+
pub fn from_boolean(value: bool) -> Self {
26+
let obj = if value {
27+
unsafe { tcl_sys::Tcl_NewBooleanObj(1) }
28+
} else {
29+
unsafe { tcl_sys::Tcl_NewBooleanObj(0) }
30+
};
31+
unsafe {
32+
Self::from_raw(obj)
33+
}
34+
}
35+
36+
pub fn from_int(value: i32) -> Self {
37+
let obj = unsafe { tcl_sys::Tcl_NewIntObj(value) };
38+
unsafe {
39+
Self::from_raw(obj)
40+
}
41+
}
42+
43+
pub fn from_double(value: f64) -> Self {
44+
let obj = unsafe { tcl_sys::Tcl_NewDoubleObj(value) };
45+
unsafe {
46+
Self::from_raw(obj)
47+
}
48+
}
49+
50+
pub fn from_long(value: i64) -> Self {
51+
let obj = unsafe { tcl_sys::Tcl_NewLongObj(value as _) };
52+
unsafe {
53+
Self::from_raw(obj)
54+
}
55+
}
56+
57+
pub fn from_list(values: &[Obj]) -> Self {
58+
let obj = unsafe { tcl_sys::Tcl_NewListObj(values.len() as i32, values.as_ptr() as *const _) };
59+
unsafe {
60+
Self::from_raw(obj)
61+
}
62+
}
63+
64+
pub fn get_string(&self) -> Option<String> {
65+
let c_str = unsafe { tcl_sys::Tcl_GetString(self.0.as_ptr()) };
66+
if c_str.is_null() {
67+
None
68+
} else {
69+
Some(unsafe { std::ffi::CStr::from_ptr(c_str) }.to_string_lossy().into_owned())
70+
}
71+
}
72+
73+
pub fn get_int(&self) -> Option<i32> {
74+
let mut value: i32 = 0;
75+
let result = unsafe { tcl_sys::Tcl_GetIntFromObj(std::ptr::null_mut(), self.0.as_ptr(), &mut value) };
76+
if result == 0 {
77+
Some(value)
78+
} else {
79+
None
80+
}
81+
}
82+
83+
pub fn get_double(&self) -> Option<f64> {
84+
let mut value: f64 = 0.0;
85+
let result = unsafe { tcl_sys::Tcl_GetDoubleFromObj(std::ptr::null_mut(), self.0.as_ptr(), &mut value) };
86+
if result == 0 {
87+
Some(value)
88+
} else {
89+
None
90+
}
91+
}
92+
93+
pub fn get_long(&self) -> Option<i64> {
94+
let mut value: i64 = 0;
95+
let result = unsafe { tcl_sys::Tcl_GetLongFromObj(std::ptr::null_mut(), self.0.as_ptr(), value as _) };
96+
if result == 0 {
97+
Some(value)
98+
} else {
99+
None
100+
}
101+
}
102+
103+
pub fn get_list(&self) -> Option<Vec<Obj>> {
104+
let mut length: i32 = 0;
105+
let mut elements: *mut *mut tcl_sys::Tcl_Obj = std::ptr::null_mut();
106+
let result = unsafe { tcl_sys::Tcl_ListObjGetElements(std::ptr::null_mut(), self.0.as_ptr(), &mut length, &mut elements) };
107+
if result == 0 {
108+
let slice = unsafe { std::slice::from_raw_parts(elements, length as usize) };
109+
Some(slice.iter().map(|&obj| Obj(NonNull::new(obj).unwrap())).collect())
110+
} else {
111+
None
112+
}
113+
}
114+
pub fn get_boolean(&self) -> Option<bool> {
115+
let mut value: i32 = 0;
116+
let result = unsafe { tcl_sys::Tcl_GetBooleanFromObj(std::ptr::null_mut(), self.0.as_ptr(), &mut value) };
117+
if result == 0 {
118+
Some(value != 0)
119+
} else {
120+
None
121+
}
122+
}
123+
124+
pub fn get_list_length(&self) -> Option<i32> {
125+
let mut length: i32 = 0;
126+
let result = unsafe { tcl_sys::Tcl_ListObjLength(std::ptr::null_mut(), self.0.as_ptr(), &mut length) };
127+
if result == 0 {
128+
Some(length)
129+
} else {
130+
None
131+
}
132+
}
133+
134+
pub fn get_list_element(&self, index: i32) -> Option<Obj> {
135+
let mut element: *mut tcl_sys::Tcl_Obj = std::ptr::null_mut();
136+
let result = unsafe { tcl_sys::Tcl_ListObjIndex(std::ptr::null_mut(), self.0.as_ptr(), index, &mut element) };
137+
if result == 0 {
138+
Some(Obj(NonNull::new(element).unwrap()))
139+
} else {
140+
None
141+
}
142+
}
143+
144+
pub fn set_string(&self, string: &str) {
145+
let c_str = std::ffi::CString::new(string).expect("Failed to create CString");
146+
unsafe { tcl_sys::Tcl_SetStringObj(self.0.as_ptr(), c_str.as_ptr(), c_str.as_bytes().len() as i32) };
147+
}
148+
149+
pub fn set_int(&self, value: i32) {
150+
unsafe { tcl_sys::Tcl_SetIntObj(self.0.as_ptr(), value) };
151+
}
152+
153+
pub fn set_double(&self, value: f64) {
154+
unsafe { tcl_sys::Tcl_SetDoubleObj(self.0.as_ptr(), value) };
155+
}
156+
157+
pub fn set_long(&self, value: i64) {
158+
unsafe { tcl_sys::Tcl_SetLongObj(self.0.as_ptr(), value as _) };
159+
}
160+
161+
pub fn set_list(&self, values: &[Obj]) {
162+
unsafe { tcl_sys::Tcl_SetListObj(self.0.as_ptr(), values.len() as i32, values.as_ptr() as *const _) };
163+
}
164+
165+
pub fn set_boolean(&self, value: bool) {
166+
unsafe { tcl_sys::Tcl_SetBooleanObj(self.0.as_ptr(), value as _) };
167+
}
168+
}
169+
170+
impl Clone for Obj {
171+
fn clone(&self) -> Self {
172+
unsafe {
173+
tcl_sys::Tcl_IncrRefCount(self.0.as_ptr());
174+
}
175+
Obj(self.0)
176+
}
177+
}
178+
179+
impl Drop for Obj {
180+
fn drop(&mut self) {
181+
unsafe {
182+
tcl_sys::Tcl_DecrRefCount(self.0.as_ptr());
183+
}
184+
}
185+
}

tcl/src/time.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
pub struct Time(pub tcl_sys::Tcl_Time);
2+
3+
impl Time {
4+
pub fn new(sec: i64, usec: i64) -> Self {
5+
let time = tcl_sys::Tcl_Time {
6+
sec: sec as _,
7+
usec: usec as _,
8+
};
9+
Time(time)
10+
}
11+
}

0 commit comments

Comments
 (0)