couchbase_lite/
value.rs

1use crate::{
2    error::{Error, Result},
3    ffi::{
4        FLArray, FLArray_Count, FLArray_Get, FLArray_IsEmpty, FLDict, FLDict_Count, FLDict_Get,
5        FLDict_IsEmpty, FLSlice, FLValue, FLValueType, FLValue_AsArray, FLValue_AsBool,
6        FLValue_AsDict, FLValue_AsDouble, FLValue_AsFloat, FLValue_AsInt, FLValue_AsString,
7        FLValue_AsUnsigned, FLValue_GetType, FLValue_IsDouble, FLValue_IsInteger,
8        FLValue_IsUnsigned,
9    },
10};
11
12#[derive(Debug, Clone, Copy)]
13pub enum ValueRef<'a> {
14    Null,
15    Bool(bool),
16    SignedInt(i64),
17    UnsignedInt(u64),
18    Float(f32),
19    Double(f64),
20    String(&'a str),
21    Array(ValueRefArray),
22    Dict(ValueRefDict),
23}
24
25impl ValueRef<'_> {
26    #[inline]
27    pub fn as_bool(&self) -> Result<bool> {
28        FromValueRef::column_result(*self)
29    }
30    #[inline]
31    pub fn as_i32(&self) -> Result<i32> {
32        FromValueRef::column_result(*self)
33    }
34    #[inline]
35    pub fn as_i64(&self) -> Result<i64> {
36        FromValueRef::column_result(*self)
37    }
38    #[inline]
39    pub fn as_u64(&self) -> Result<u64> {
40        FromValueRef::column_result(*self)
41    }
42    #[inline]
43    pub fn as_f32(&self) -> Result<f32> {
44        FromValueRef::column_result(*self)
45    }
46    #[inline]
47    pub fn as_f64(&self) -> Result<f64> {
48        FromValueRef::column_result(*self)
49    }
50    #[inline]
51    pub fn as_str(&self) -> Result<&str> {
52        FromValueRef::column_result(*self)
53    }
54    #[inline]
55    pub fn is_null(&self) -> bool {
56        matches!(self, ValueRef::Null)
57    }
58    pub(crate) unsafe fn new(value: FLValue) -> Self {
59        use FLValueType::*;
60        match FLValue_GetType(value) {
61            kFLUndefined | kFLNull => ValueRef::Null,
62            kFLBoolean => ValueRef::Bool(FLValue_AsBool(value)),
63            kFLNumber => {
64                if FLValue_IsUnsigned(value) {
65                    ValueRef::UnsignedInt(FLValue_AsUnsigned(value))
66                } else if FLValue_IsInteger(value) {
67                    ValueRef::SignedInt(FLValue_AsInt(value))
68                } else if FLValue_IsDouble(value) {
69                    ValueRef::Double(FLValue_AsDouble(value))
70                } else {
71                    ValueRef::Float(FLValue_AsFloat(value))
72                }
73            }
74            kFLString => {
75                let s: &str = FLValue_AsString(value).try_into().expect("not valid utf-8");
76                ValueRef::String(s)
77            }
78            kFLArray => ValueRef::Array(ValueRefArray(FLValue_AsArray(value))),
79            kFLDict => ValueRef::Dict(ValueRefDict(FLValue_AsDict(value))),
80            kFLData => unimplemented!(),
81        }
82    }
83}
84
85#[derive(Debug, Clone, Copy)]
86#[repr(transparent)]
87pub struct ValueRefArray(FLArray);
88
89impl ValueRefArray {
90    #[inline]
91    pub fn len(&self) -> u32 {
92        unsafe { FLArray_Count(self.0) }
93    }
94    #[inline]
95    pub fn is_empty(&self) -> bool {
96        unsafe { FLArray_IsEmpty(self.0) }
97    }
98    pub(crate) unsafe fn get_raw(&self, idx: u32) -> FLValue {
99        FLArray_Get(self.0, idx)
100    }
101    #[inline]
102    pub fn get<'a>(&'a self, idx: u32) -> ValueRef<'a> {
103        unsafe { ValueRef::new(self.get_raw(idx)) }
104    }
105}
106
107#[derive(Debug, Clone, Copy)]
108#[repr(transparent)]
109pub struct ValueRefDict(FLDict);
110
111impl ValueRefDict {
112    #[inline]
113    pub fn len(&self) -> u32 {
114        unsafe { FLDict_Count(self.0) }
115    }
116    #[inline]
117    pub fn is_empty(&self) -> bool {
118        unsafe { FLDict_IsEmpty(self.0) }
119    }
120    pub(crate) unsafe fn get_raw(&self, key: FLSlice) -> FLValue {
121        FLDict_Get(self.0, key)
122    }
123    #[inline]
124    pub fn get<'a>(&'a self, key: FLSlice) -> ValueRef<'a> {
125        unsafe { ValueRef::new(self.get_raw(key)) }
126    }
127}
128
129pub trait FromValueRef<'a>: Sized {
130    fn column_result(val: ValueRef<'a>) -> Result<Self>;
131}
132
133impl<'a> FromValueRef<'a> for bool {
134    #[inline]
135    fn column_result(val: ValueRef<'a>) -> Result<Self> {
136        if let ValueRef::Bool(x) = val {
137            Ok(x)
138        } else {
139            Err(Error::LogicError(
140                format!("Wrong ValueRef type, expect Bool, got {val:?}").into(),
141            ))
142        }
143    }
144}
145
146impl<'a> FromValueRef<'a> for &'a str {
147    #[inline]
148    fn column_result(val: ValueRef<'a>) -> Result<Self> {
149        if let ValueRef::String(x) = val {
150            Ok(x)
151        } else {
152            Err(Error::LogicError(
153                format!("Wrong ValueRef type, expect String, got {val:?}").into(),
154            ))
155        }
156    }
157}
158
159impl<'a> FromValueRef<'a> for u16 {
160    fn column_result(val: ValueRef<'a>) -> Result<Self> {
161        match val {
162            ValueRef::SignedInt(x) => u16::try_from(x).map_err(|err| {
163                Error::LogicError(
164                    format!("ValueRef(Signed) {x} to u16 conversation error: {err}").into(),
165                )
166            }),
167            ValueRef::UnsignedInt(x) => u16::try_from(x).map_err(|err| {
168                Error::LogicError(
169                    format!("ValueRef(Unsigned) {x} to u16 conversation error: {err}").into(),
170                )
171            }),
172            _ => Err(Error::LogicError(
173                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (u16) got {val:?}")
174                    .into(),
175            )),
176        }
177    }
178}
179
180impl<'a> FromValueRef<'a> for i32 {
181    fn column_result(val: ValueRef<'a>) -> Result<Self> {
182        match val {
183            ValueRef::SignedInt(val) => i32::try_from(val).map_err(|err| {
184                Error::LogicError(format!("i64->i32 conversation failure: {err}").into())
185            }),
186            ValueRef::UnsignedInt(val) => i32::try_from(val).map_err(|err| {
187                Error::LogicError(format!("u64->i32 conversation failure: {err}").into())
188            }),
189            _ => Err(Error::LogicError(
190                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (i32) got {val:?}")
191                    .into(),
192            )),
193        }
194    }
195}
196
197impl<'a> FromValueRef<'a> for u32 {
198    fn column_result(val: ValueRef<'a>) -> Result<Self> {
199        match val {
200            ValueRef::SignedInt(x) => u32::try_from(x).map_err(|err| {
201                Error::LogicError(
202                    format!("ValueRef(Signed) {x} to u32 conversation error: {err}").into(),
203                )
204            }),
205            ValueRef::UnsignedInt(x) => u32::try_from(x).map_err(|err| {
206                Error::LogicError(
207                    format!("ValueRef(Unsigned) {x} to u32 conversation error: {err}").into(),
208                )
209            }),
210            _ => Err(Error::LogicError(
211                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (u32) got {val:?}")
212                    .into(),
213            )),
214        }
215    }
216}
217
218impl<'a> FromValueRef<'a> for u64 {
219    fn column_result(val: ValueRef<'a>) -> Result<Self> {
220        match val {
221            ValueRef::SignedInt(x) => u64::try_from(x).map_err(|err| {
222                Error::LogicError(
223                    format!("ValueRef(Signed) {x} to u32 conversation error: {err}").into(),
224                )
225            }),
226            ValueRef::UnsignedInt(x) => Ok(x),
227            _ => Err(Error::LogicError(
228                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (u64) got {val:?}")
229                    .into(),
230            )),
231        }
232    }
233}
234
235impl<'a> FromValueRef<'a> for i64 {
236    fn column_result(val: ValueRef<'a>) -> Result<Self> {
237        match val {
238            ValueRef::SignedInt(x) => Ok(x),
239            ValueRef::UnsignedInt(x) => i64::try_from(x).map_err(|err| {
240                Error::LogicError(
241                    format!("ValueRef (UnsignedInt) to i64 conversation failed: {err}").into(),
242                )
243            }),
244            _ => Err(Error::LogicError(
245                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (i64) got {val:?}")
246                    .into(),
247            )),
248        }
249    }
250}
251
252impl<'a> FromValueRef<'a> for usize {
253    fn column_result(val: ValueRef<'a>) -> Result<Self> {
254        match val {
255            ValueRef::SignedInt(x) => usize::try_from(x).map_err(|err| {
256                Error::LogicError(
257                    format!("ValueRef(Signed) {x} to usize conversation error: {err}").into(),
258                )
259            }),
260            ValueRef::UnsignedInt(x) => usize::try_from(x).map_err(|err| {
261                Error::LogicError(
262                    format!("ValueRef(Unsigned) {x} to usize conversation error: {err}").into(),
263                )
264            }),
265            _ => Err(Error::LogicError(
266                format!("Wrong ValueRef type, expect SignedInt|UnsignedInt (usize) got {val:?}")
267                    .into(),
268            )),
269        }
270    }
271}
272
273impl<'a> FromValueRef<'a> for f32 {
274    #[inline]
275    fn column_result(val: ValueRef<'a>) -> Result<Self> {
276        if let ValueRef::Float(x) = val {
277            Ok(x)
278        } else {
279            Err(Error::LogicError(
280                format!("Wrong ValueRef type, expect Float, got {val:?}").into(),
281            ))
282        }
283    }
284}
285
286impl<'a> FromValueRef<'a> for f64 {
287    #[inline]
288    fn column_result(val: ValueRef<'a>) -> Result<Self> {
289        match val {
290            ValueRef::Float(x) => Ok(f64::from(x)),
291            ValueRef::Double(x) => Ok(x),
292            _ => Err(Error::LogicError(
293                format!("Wrong ValueRef type, expect Float/Double, got {val:?}").into(),
294            )),
295        }
296    }
297}