1use couchbase_lite_core_sys::{FLValue_AsString, FLValue_GetType};
2
3use crate::{
4 ffi::{
5 FLDict, FLDict_Get, FLError, FLMutableDict_New, FLMutableDict_Release,
6 FLMutableDict_SetInt, FLMutableDict_SetString, FLSlice, FLValueType, FLValue_AsData,
7 _FLDict, _FLValue,
8 },
9 Error, NonNullConst,
10};
11use std::{borrow::Borrow, marker::PhantomData, ptr::NonNull};
12
13#[repr(transparent)]
14pub struct MutableDict(NonNull<_FLDict>);
15
16impl MutableDict {
17 #[inline]
18 pub fn new() -> Result<Self, Error> {
19 let dict = unsafe { FLMutableDict_New() };
20 NonNull::new(dict)
21 .ok_or(Error::Fleece(FLError::kFLMemoryError))
22 .map(MutableDict)
23 }
24 #[inline]
25 pub fn set_string(&mut self, key: &str, value: &str) {
26 unsafe { FLMutableDict_SetString(self.0.as_ptr(), key.into(), value.into()) };
27 }
28 #[inline]
29 pub fn set_i64(&mut self, key: &str, value: i64) {
30 unsafe { FLMutableDict_SetInt(self.0.as_ptr(), key.into(), value) };
31 }
32 #[inline]
33 pub fn as_dict(&self) -> NonNullConst<_FLDict> {
34 self.0.into()
35 }
36 #[inline]
37 pub fn as_fleece_slice(&self) -> FLSlice {
38 let value: NonNull<_FLValue> = self.0.cast();
39 unsafe { FLValue_AsData(value.as_ptr()) }
40 }
41}
42
43impl Drop for MutableDict {
44 #[inline]
45 fn drop(&mut self) {
46 unsafe { FLMutableDict_Release(self.0.as_ptr()) };
47 }
48}
49
50pub struct Dict<'a> {
51 inner: NonNullConst<_FLDict>,
52 marker: PhantomData<&'a FLDict>,
53}
54
55impl<'a> Dict<'a> {
56 #[inline]
57 pub fn new(dict: &FLDict) -> Option<Self> {
58 let inner = NonNullConst::new(*dict)?;
59 Some(Self {
60 inner,
61 marker: PhantomData,
62 })
63 }
64 pub fn get_as_str(&self, prop_name: &str) -> Option<&str> {
65 let val = unsafe { FLDict_Get(self.inner.as_ptr(), prop_name.into()) };
66 let val = NonNullConst::new(val)?;
67 if unsafe { FLValue_GetType(val.as_ptr()) } == FLValueType::kFLString {
68 let raw_s = unsafe { FLValue_AsString(val.as_ptr()) };
69 raw_s.try_into().ok()
70 } else {
71 None
72 }
73 }
74}
75
76impl<'a> Borrow<NonNullConst<_FLDict>> for Dict<'a> {
77 #[inline]
78 fn borrow(&self) -> &NonNullConst<_FLDict> {
79 &self.inner
80 }
81}