1pub mod tables;
12pub mod engine;
13pub mod spelling;
14
15use std::ffi::{CStr, CString};
16use std::os::raw::c_char;
17
18#[derive(Clone, Copy, PartialEq, Eq)]
20pub enum Method { Telex, Vni, TeipVni, Viqr }
21
22pub struct SkeyEngine {
24 method: Method,
25 modern: bool,
26 short_w: bool,
27}
28
29impl SkeyEngine {
30 pub fn new(method: Method) -> Self {
31 SkeyEngine { method, modern: true, short_w: false }
32 }
33
34 pub fn set_method(&mut self, method: Method) { self.method = method; }
35 pub fn set_modern(&mut self, v: bool) { self.modern = v; }
36 pub fn set_short_w(&mut self, v: bool) { self.short_w = v; }
37
38 pub fn transform(&self, input: &str) -> String {
39 match self.method {
40 Method::Telex => engine::convert_telex(input, self.modern, self.short_w),
41 Method::Vni => engine::convert_vni(input, self.modern, self.short_w),
42 Method::TeipVni => engine::convert_teip_vni(input, self.modern, self.short_w),
43 Method::Viqr => engine::convert_viqr(input),
44 }
45 }
46
47 pub fn is_valid(s: &str) -> bool {
48 spelling::is_valid_cvc(s)
49 }
50}
51
52#[unsafe(no_mangle)]
55pub unsafe extern "C" fn skey_engine_new(method: i32) -> *mut SkeyEngine {
56 let m = match method {
57 0 => Method::Telex, 1 => Method::Vni, 2 => Method::Viqr, 3 => Method::TeipVni, _ => Method::Telex,
62 };
63 Box::into_raw(Box::new(SkeyEngine::new(m)))
64}
65
66#[unsafe(no_mangle)]
67pub unsafe extern "C" fn skey_engine_free(engine: *mut SkeyEngine) {
68 if !engine.is_null() { unsafe { drop(Box::from_raw(engine)); } }
69}
70
71#[unsafe(no_mangle)]
72pub unsafe extern "C" fn skey_engine_set_method(engine: *mut SkeyEngine, method: i32) {
73 if engine.is_null() { return; }
74 let m = match method {
75 0 => Method::Telex,
76 1 => Method::Vni,
77 2 => Method::Viqr,
78 3 => Method::TeipVni,
79 _ => Method::Telex,
80 };
81 unsafe { (*engine).set_method(m); }
82}
83
84#[unsafe(no_mangle)]
86pub unsafe extern "C" fn skey_engine_set_tone_style(e: *mut SkeyEngine, v: i32) {
87 if !e.is_null() { unsafe { (*e).set_modern(v != 0); } }
88}
89#[unsafe(no_mangle)]
90pub unsafe extern "C" fn skey_engine_set_free_marking(_e: *mut SkeyEngine, _v: i32) {}
91#[unsafe(no_mangle)]
92pub unsafe extern "C" fn skey_engine_set_short_w(e: *mut SkeyEngine, v: i32) {
93 if !e.is_null() { unsafe { (*e).set_short_w(v != 0); } }
94}
95#[unsafe(no_mangle)]
96pub unsafe extern "C" fn skey_engine_set_bracket_uo(_e: *mut SkeyEngine, _v: i32) {}
97
98#[unsafe(no_mangle)]
99pub unsafe extern "C" fn skey_engine_transform(
100 engine: *const SkeyEngine,
101 input: *const c_char,
102) -> *mut c_char {
103 if engine.is_null() || input.is_null() { return std::ptr::null_mut(); }
104 let e = unsafe { &*engine };
105 let s = match unsafe { CStr::from_ptr(input) }.to_str() {
106 Ok(s) => s, Err(_) => return std::ptr::null_mut(),
107 };
108 CString::new(e.transform(s)).unwrap_or_default().into_raw()
109}
110
111#[unsafe(no_mangle)]
112pub unsafe extern "C" fn skey_engine_is_valid(s: *const c_char) -> i32 {
113 if s.is_null() { return 0; }
114 let s = match unsafe { CStr::from_ptr(s) }.to_str() {
115 Ok(s) => s, Err(_) => return 0,
116 };
117 if SkeyEngine::is_valid(s) { 1 } else { 0 }
118}
119
120#[unsafe(no_mangle)]
121pub unsafe extern "C" fn skey_free_string(s: *mut c_char) {
122 if !s.is_null() { unsafe { drop(CString::from_raw(s)); } }
123}