1use lotus_script_sys::{FfiObject, FromFfi};
6use lotus_shared::content::ContentId;
7
8pub trait VariableType {
12 type Output;
16
17 fn get_var(name: &str) -> Self::Output;
21 fn set_var(name: &str, var: Self);
25}
26
27#[doc(hidden)]
28pub enum Persistence {
29 Session,
30 Permanent,
31}
32
33macro_rules! impl_variable_type {
34 ($type:ty, $get:ident, $set:ident) => {
35 impl VariableType for $type {
36 type Output = $type;
37
38 fn get_var(name: &str) -> Self::Output {
39 let name = FfiObject::new(&name);
40 unsafe { lotus_script_sys::var::$get(name.packed()) as _ }
41 }
42
43 fn set_var(name: &str, var: Self) {
44 let name = FfiObject::new(&name);
45 unsafe { lotus_script_sys::var::$set(name.packed(), var as _) }
46 }
47 }
48 };
49}
50
51impl_variable_type!(i8, get_i64, set_i64);
52impl_variable_type!(i16, get_i64, set_i64);
53impl_variable_type!(i32, get_i64, set_i64);
54impl_variable_type!(i64, get_i64, set_i64);
55
56impl_variable_type!(u8, get_i64, set_i64);
57impl_variable_type!(u16, get_i64, set_i64);
58impl_variable_type!(u32, get_i64, set_i64);
59impl_variable_type!(u64, get_i64, set_i64);
60
61impl_variable_type!(f32, get_f64, set_f64);
62impl_variable_type!(f64, get_f64, set_f64);
63
64impl VariableType for bool {
65 type Output = bool;
66
67 fn get_var(name: &str) -> Self::Output {
68 let name = FfiObject::new(&name);
69 unsafe { lotus_script_sys::var::get_bool(name.packed()) != 0 }
70 }
71
72 fn set_var(name: &str, var: Self) {
73 let name = FfiObject::new(&name);
74 unsafe {
75 lotus_script_sys::var::set_bool(
76 name.packed(),
77 match var {
78 true => 1,
79 false => 0,
80 },
81 )
82 }
83 }
84}
85
86impl VariableType for String {
87 type Output = String;
88
89 fn get_var(name: &str) -> Self::Output {
90 let name = FfiObject::new(&name);
91 let ptr = unsafe { lotus_script_sys::var::get_string(name.packed()) };
92 String::from_ffi(ptr)
93 }
94
95 fn set_var(name: &str, var: Self) {
96 let name = FfiObject::new(&name);
97 let value = FfiObject::new(&var);
98 unsafe { lotus_script_sys::var::set_string(name.packed(), value.packed()) }
99 }
100}
101
102impl VariableType for &str {
103 type Output = String;
104
105 fn get_var(name: &str) -> Self::Output {
106 let name = FfiObject::new(&name);
107 let ptr = unsafe { lotus_script_sys::var::get_string(name.packed()) };
108 String::from_ffi(ptr)
109 }
110
111 fn set_var(name: &str, var: Self) {
112 let name = FfiObject::new(&name);
113 let value = FfiObject::new(&var.to_string());
114 unsafe { lotus_script_sys::var::set_string(name.packed(), value.packed()) }
115 }
116}
117
118impl VariableType for ContentId {
119 type Output = ContentId;
120
121 fn get_var(name: &str) -> Self {
122 let name = FfiObject::new(&name);
123 let ptr = unsafe { lotus_script_sys::var::get_content_id(name.packed()) };
124 FfiObject::from_packed(ptr).deserialize()
125 }
126
127 fn set_var(name: &str, var: Self) {
128 let name = FfiObject::new(&name);
129 let value = FfiObject::new(&var);
130 unsafe { lotus_script_sys::var::set_content_id(name.packed(), value.packed()) }
131 }
132}
133
134pub struct Variable<T> {
138 name: String,
139 _phantom: std::marker::PhantomData<T>,
140}
141
142impl<T> Variable<T> {
143 pub fn new(name: &str) -> Self {
147 Self {
148 name: name.to_string(),
149 _phantom: std::marker::PhantomData,
150 }
151 }
152}
153
154impl<T: VariableType> Variable<T> {
155 pub fn get(&self) -> T::Output {
159 T::get_var(&self.name)
160 }
161
162 pub fn set(&self, value: T) {
166 T::set_var(&self.name, value);
167 }
168}
169
170pub fn get_var<T: VariableType>(name: &str) -> T::Output {
174 T::get_var(name)
175}
176
177pub fn set_var<T: VariableType>(name: &str, var: T) {
181 T::set_var(name, var);
182}