1use core::{
6 fmt, marker::PhantomData, ops::Deref, ptr, ptr::NonNull, slice, str,
7};
8
9use crate::c;
10
11#[derive(Copy, Clone)]
13#[repr(transparent)]
14pub struct Object<'a> {
15 c: c::GgObject,
16 phantom: PhantomData<UnpackedObject<'a>>,
17}
18
19impl fmt::Debug for Object<'_> {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 self.unpack().fmt(f)
22 }
23}
24
25#[derive(Debug)]
27#[repr(u8)]
28pub enum UnpackedObject<'a> {
29 Null = 0,
31 Bool(bool) = 1,
33 I64(i64) = 2,
35 F64(f64) = 3,
37 Buf(&'a str) = 4,
39 List(List<'a>) = 5,
41 Map(Map<'a>) = 6,
43}
44
45impl<'a> Object<'a> {
46 pub const NULL: Self = Self {
48 c: c::GgObject { _private: [0; _] },
49 phantom: PhantomData,
50 };
51
52 #[must_use]
63 pub fn bool(b: bool) -> Self {
64 Self {
65 c: unsafe { c::gg_obj_bool(b) },
66 phantom: PhantomData,
67 }
68 }
69
70 #[must_use]
72 pub fn i64(i: i64) -> Self {
73 Self {
74 c: unsafe { c::gg_obj_i64(i) },
75 phantom: PhantomData,
76 }
77 }
78
79 #[must_use]
81 pub fn f64(f: f64) -> Self {
82 Self {
83 c: unsafe { c::gg_obj_f64(f) },
84 phantom: PhantomData,
85 }
86 }
87
88 #[must_use]
100 pub fn buf(buf: &'a str) -> Self {
101 Self {
102 c: unsafe { c::gg_obj_buf(buf.into()) },
103 phantom: PhantomData,
104 }
105 }
106
107 #[must_use]
121 pub fn list(list: &'a [Object<'a>]) -> Self {
122 Self {
123 c: unsafe { c::gg_obj_list(list.into()) },
124 phantom: PhantomData,
125 }
126 }
127
128 #[must_use]
142 pub fn map(map: &'a [Kv<'a>]) -> Self {
143 Self {
144 c: unsafe { c::gg_obj_map(map.into()) },
145 phantom: PhantomData,
146 }
147 }
148}
149
150unsafe fn slice_from_c<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
151 let ptr = NonNull::new(ptr.cast_mut()).unwrap_or_else(|| {
152 assert_eq!(len, 0, "null pointer with non-zero length");
153 NonNull::dangling()
154 });
155 unsafe { NonNull::slice_from_raw_parts(ptr, len).as_ref() }
156}
157
158impl<'a> Object<'a> {
159 #[must_use]
190 pub fn unpack(&self) -> UnpackedObject<'_> {
191 use c::GgObjectType::*;
192
193 unsafe {
194 match c::gg_obj_type(self.c) {
195 GG_TYPE_NULL => UnpackedObject::Null,
196 GG_TYPE_BOOLEAN => {
197 UnpackedObject::Bool(c::gg_obj_into_bool(self.c))
198 }
199 GG_TYPE_I64 => UnpackedObject::I64(c::gg_obj_into_i64(self.c)),
200 GG_TYPE_F64 => UnpackedObject::F64(c::gg_obj_into_f64(self.c)),
201 GG_TYPE_BUF => {
202 let buf = c::gg_obj_into_buf(self.c);
203 let ptr = slice_from_c(buf.data, buf.len);
204 UnpackedObject::Buf(str::from_utf8_unchecked(ptr))
205 }
206 GG_TYPE_LIST => {
207 let list = c::gg_obj_into_list(self.c);
208 UnpackedObject::List(List(slice_from_c(
209 list.items.cast::<Object<'a>>(),
210 list.len,
211 )))
212 }
213 GG_TYPE_MAP => {
214 let map = c::gg_obj_into_map(self.c);
215 UnpackedObject::Map(Map(slice_from_c(
216 map.pairs.cast::<Kv<'a>>(),
217 map.len,
218 )))
219 }
220 }
221 }
222 }
223}
224
225impl Default for Object<'_> {
226 fn default() -> Self {
227 Self::NULL
228 }
229}
230
231impl From<bool> for Object<'_> {
232 fn from(b: bool) -> Self {
233 Self::bool(b)
234 }
235}
236
237impl From<i64> for Object<'_> {
238 fn from(i: i64) -> Self {
239 Self::i64(i)
240 }
241}
242
243impl From<f64> for Object<'_> {
244 fn from(f: f64) -> Self {
245 Self::f64(f)
246 }
247}
248
249impl<'a> From<&'a str> for Object<'a> {
250 fn from(s: &'a str) -> Self {
251 Self::buf(s)
252 }
253}
254
255impl<'a> From<&'a [Object<'a>]> for Object<'a> {
256 fn from(list: &'a [Object<'a>]) -> Self {
257 Self::list(list)
258 }
259}
260
261impl<'a> From<&'a [Kv<'a>]> for Object<'a> {
262 fn from(map: &'a [Kv<'a>]) -> Self {
263 Self::map(map)
264 }
265}
266
267impl<'a> From<Map<'a>> for Object<'a> {
268 fn from(map: Map<'a>) -> Self {
269 Self::map(map.0)
270 }
271}
272
273impl<'a> From<List<'a>> for Object<'a> {
274 fn from(list: List<'a>) -> Self {
275 Self::list(list.0)
276 }
277}
278
279#[derive(Copy, Clone)]
281#[repr(transparent)]
282pub struct Kv<'a> {
283 c: c::GgKV,
284 phantom_key: PhantomData<&'a str>,
285 phantom_value: PhantomData<Object<'a>>,
286}
287
288impl fmt::Debug for Kv<'_> {
289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290 f.debug_struct("Kv")
291 .field("key", &self.key())
292 .field("val", self.val())
293 .finish()
294 }
295}
296
297impl<'a> Kv<'a> {
298 #[must_use]
309 pub fn new(key: &'a str, value: Object<'a>) -> Self {
310 Self {
311 c: unsafe { c::gg_kv(key.into(), value.c) },
312 phantom_key: PhantomData,
313 phantom_value: PhantomData,
314 }
315 }
316
317 #[must_use]
320 pub fn key(&self) -> &str {
321 let buf = unsafe { c::gg_kv_key(self.c) };
322 unsafe {
323 str::from_utf8_unchecked(slice::from_raw_parts(buf.data, buf.len))
324 }
325 }
326
327 #[must_use]
338 pub fn val(&self) -> &Object<'a> {
339 unsafe {
340 c::gg_kv_val((&raw const self.c).cast_mut())
341 .cast::<Object>()
342 .as_ref()
343 .unwrap_unchecked()
344 }
345 }
346}
347
348impl<'a> From<Map<'a>> for &'a [Kv<'a>] {
349 fn from(map: Map<'a>) -> Self {
350 map.0
351 }
352}
353
354impl<'a> From<List<'a>> for &'a [Object<'a>] {
355 fn from(list: List<'a>) -> Self {
356 list.0
357 }
358}
359
360#[derive(Debug, Clone, Copy)]
362#[repr(transparent)]
363pub struct Map<'a>(pub &'a [Kv<'a>]);
364
365#[derive(Debug, Clone, Copy)]
367#[repr(transparent)]
368pub struct List<'a>(pub &'a [Object<'a>]);
369
370impl Map<'_> {
371 #[must_use]
387 pub fn get(&self, key: &str) -> Option<&Object<'_>> {
388 let map: c::GgMap = self.0.into();
389 let mut result: *mut c::GgObject = ptr::null_mut();
390 if unsafe { c::gg_map_get(map, key.into(), &raw mut result) } {
391 Some(unsafe {
392 NonNull::new(result.cast::<Object>())
393 .unwrap_unchecked()
394 .as_ref()
395 })
396 } else {
397 None
398 }
399 }
400}
401
402impl<'a> From<&'a [Kv<'a>]> for Map<'a> {
403 fn from(slice: &'a [Kv<'a>]) -> Self {
404 Map(slice)
405 }
406}
407
408impl From<&[Kv<'_>]> for c::GgMap {
409 fn from(kvs: &[Kv<'_>]) -> Self {
410 Self {
411 pairs: kvs.as_ptr().cast_mut().cast::<c::GgKV>(),
412 len: kvs.len(),
413 }
414 }
415}
416
417impl<'a> From<&'a [Object<'a>]> for List<'a> {
418 fn from(slice: &'a [Object<'a>]) -> Self {
419 List(slice)
420 }
421}
422
423impl From<&[Object<'_>]> for c::GgList {
424 fn from(objs: &[Object<'_>]) -> Self {
425 Self {
426 items: objs.as_ptr().cast_mut().cast::<c::GgObject>(),
427 len: objs.len(),
428 }
429 }
430}
431
432impl<'a> Deref for Map<'a> {
433 type Target = [Kv<'a>];
434 fn deref(&self) -> &[Kv<'a>] {
435 self.0
436 }
437}
438
439impl<'a> Deref for List<'a> {
440 type Target = [Object<'a>];
441 fn deref(&self) -> &[Object<'a>] {
442 self.0
443 }
444}