1use super::*;
4
5#[unsafe(no_mangle)]
11pub extern "C" fn kui_value_null() -> *mut KuiValue {
12 Box::into_raw(Box::new(KuiValue(Value::Null)))
13}
14
15#[unsafe(no_mangle)]
17pub extern "C" fn kui_value_bool(v: bool) -> *mut KuiValue {
18 Box::into_raw(Box::new(KuiValue(Value::Bool(v))))
19}
20
21#[unsafe(no_mangle)]
23pub extern "C" fn kui_value_int(v: i64) -> *mut KuiValue {
24 Box::into_raw(Box::new(KuiValue(Value::Int(v))))
25}
26
27#[unsafe(no_mangle)]
29pub extern "C" fn kui_value_float(v: f64) -> *mut KuiValue {
30 Box::into_raw(Box::new(KuiValue(Value::Float(v))))
31}
32
33#[unsafe(no_mangle)]
35pub extern "C" fn kui_value_str(s: KuiStr) -> *mut KuiValue {
36 guard(std::ptr::null_mut(), || {
37 Box::into_raw(Box::new(KuiValue(Value::Str(kstr(s).into_owned()))))
38 })
39}
40
41#[unsafe(no_mangle)]
45pub extern "C" fn kui_value_map() -> *mut KuiValue {
46 Box::into_raw(Box::new(KuiValue(Value::Map(Vec::new()))))
47}
48
49#[unsafe(no_mangle)]
52pub extern "C" fn kui_value_list() -> *mut KuiValue {
53 Box::into_raw(Box::new(KuiValue(Value::List(Vec::new()))))
54}
55
56#[unsafe(no_mangle)]
59pub extern "C" fn kui_value_list_push(list: *mut KuiValue, val: *mut KuiValue) {
60 guard((), || {
61 if val.is_null() {
62 return;
63 }
64 let val = unsafe { Box::from_raw(val) };
65 let Some(list) = (unsafe { list.as_mut() }) else {
66 return;
67 };
68 if let Value::List(items) = &mut list.0 {
69 items.push(val.0);
70 }
71 });
72}
73
74#[unsafe(no_mangle)]
77pub extern "C" fn kui_value_map_set(map: *mut KuiValue, key: KuiStr, val: *mut KuiValue) {
78 guard((), || {
79 if val.is_null() {
80 return;
81 }
82 let val = unsafe { Box::from_raw(val) };
83 let Some(map) = (unsafe { map.as_mut() }) else {
84 return;
85 };
86 if let Value::Map(entries) = &mut map.0 {
87 let key = kstr(key).into_owned();
88 if let Some(e) = entries.iter_mut().find(|(k, _)| *k == key) {
89 e.1 = val.0;
90 } else {
91 entries.push((key, val.0));
92 }
93 }
94 });
95}
96
97#[unsafe(no_mangle)]
99pub extern "C" fn kui_value_get(v: *const KuiValue, key: KuiStr) -> *const KuiValue {
100 guard(std::ptr::null(), || {
101 let Some(v) = (unsafe { v.as_ref() }) else {
102 return std::ptr::null();
103 };
104 match v.0.get(&kstr(key)) {
105 Some(inner) => (inner as *const Value).cast(),
107 None => std::ptr::null(),
108 }
109 })
110}
111
112#[unsafe(no_mangle)]
115pub extern "C" fn kui_value_len(v: *const KuiValue) -> usize {
116 guard(0, || match unsafe { v.as_ref() }.map(|v| &v.0) {
117 Some(Value::List(items)) => items.len(),
118 Some(Value::Map(entries)) => entries.len(),
119 _ => 0,
120 })
121}
122
123#[unsafe(no_mangle)]
127pub extern "C" fn kui_value_at(v: *const KuiValue, i: usize) -> *const KuiValue {
128 guard(std::ptr::null(), || {
129 match unsafe { v.as_ref() }.map(|v| &v.0) {
130 Some(Value::List(items)) => items
132 .get(i)
133 .map_or(std::ptr::null(), |inner| (inner as *const Value).cast()),
134 _ => std::ptr::null(),
135 }
136 })
137}
138
139#[unsafe(no_mangle)]
143pub extern "C" fn kui_value_entry(
144 v: *const KuiValue,
145 i: usize,
146 key: *mut KuiStr,
147) -> *const KuiValue {
148 guard(std::ptr::null(), || {
149 match unsafe { v.as_ref() }.map(|v| &v.0) {
150 Some(Value::Map(entries)) => match entries.get(i) {
151 Some((k, inner)) => {
152 if !key.is_null() {
153 unsafe {
154 key.write(KuiStr {
155 ptr: k.as_ptr(),
156 len: k.len(),
157 })
158 };
159 }
160 (inner as *const Value).cast()
161 }
162 None => std::ptr::null(),
163 },
164 _ => std::ptr::null(),
165 }
166 })
167}
168
169#[unsafe(no_mangle)]
174pub extern "C" fn kui_value_as_float(v: *const KuiValue, out: *mut f64) -> bool {
175 guard(false, || {
176 let (Some(v), Some(out)) = (unsafe { v.as_ref() }, unsafe { out.as_mut() }) else {
177 return false;
178 };
179 match v.0.as_float() {
180 Some(f) => {
181 *out = f;
182 true
183 }
184 None => false,
185 }
186 })
187}
188
189#[unsafe(no_mangle)]
193pub extern "C" fn kui_value_as_bool(v: *const KuiValue, out: *mut bool) -> bool {
194 guard(false, || {
195 let (Some(v), Some(out)) = (unsafe { v.as_ref() }, unsafe { out.as_mut() }) else {
196 return false;
197 };
198 match v.0.as_bool() {
199 Some(b) => {
200 *out = b;
201 true
202 }
203 None => false,
204 }
205 })
206}
207
208#[unsafe(no_mangle)]
212pub extern "C" fn kui_value_is_null(v: *const KuiValue) -> bool {
213 guard(true, || match unsafe { v.as_ref() } {
214 Some(v) => matches!(v.0, Value::Null),
215 None => true,
216 })
217}
218
219#[unsafe(no_mangle)]
222pub extern "C" fn kui_value_as_int(v: *const KuiValue, out: *mut i64) -> bool {
223 guard(false, || {
224 let (Some(v), Some(out)) = (unsafe { v.as_ref() }, unsafe { out.as_mut() }) else {
225 return false;
226 };
227 match v.0.as_int() {
228 Some(i) => {
229 *out = i;
230 true
231 }
232 None => false,
233 }
234 })
235}
236
237#[unsafe(no_mangle)]
239pub extern "C" fn kui_value_as_str(v: *const KuiValue, out: *mut KuiStr) -> bool {
240 guard(false, || {
241 let (Some(v), Some(out)) = (unsafe { v.as_ref() }, unsafe { out.as_mut() }) else {
242 return false;
243 };
244 match v.0.as_str() {
245 Some(s) => {
246 *out = KuiStr {
247 ptr: s.as_ptr(),
248 len: s.len(),
249 };
250 true
251 }
252 None => false,
253 }
254 })
255}
256
257#[unsafe(no_mangle)]
260pub extern "C" fn kui_value_free(v: *mut KuiValue) {
261 if !v.is_null() {
262 drop(unsafe { Box::from_raw(v) });
263 }
264}