discord_cassandra_cpp/cassandra/
value.rs

1use crate::cassandra::data_type::ConstDataType;
2use crate::cassandra::error::*;
3use crate::cassandra::inet::Inet;
4use crate::cassandra::iterator::MapIterator;
5use crate::cassandra::iterator::SetIterator;
6use crate::cassandra::iterator::UserTypeIterator;
7use crate::cassandra::util::{Protected, ProtectedInner};
8use crate::cassandra::uuid::Uuid;
9
10use crate::cassandra_sys::cass_collection_append_decimal;
11use crate::cassandra_sys::cass_iterator_fields_from_user_type;
12use crate::cassandra_sys::cass_iterator_from_collection;
13use crate::cassandra_sys::cass_iterator_from_map;
14use crate::cassandra_sys::cass_true;
15use crate::cassandra_sys::cass_value_data_type;
16use crate::cassandra_sys::cass_value_get_bool;
17use crate::cassandra_sys::cass_value_get_bytes;
18use crate::cassandra_sys::cass_value_get_double;
19use crate::cassandra_sys::cass_value_get_float;
20use crate::cassandra_sys::cass_value_get_inet;
21use crate::cassandra_sys::cass_value_get_int16;
22use crate::cassandra_sys::cass_value_get_int32;
23use crate::cassandra_sys::cass_value_get_int64;
24use crate::cassandra_sys::cass_value_get_int8;
25use crate::cassandra_sys::cass_value_get_string;
26use crate::cassandra_sys::cass_value_get_uint32;
27use crate::cassandra_sys::cass_value_get_uuid;
28use crate::cassandra_sys::cass_value_is_collection;
29use crate::cassandra_sys::cass_value_is_null;
30use crate::cassandra_sys::cass_value_item_count;
31use crate::cassandra_sys::cass_value_primary_sub_type;
32use crate::cassandra_sys::cass_value_secondary_sub_type;
33use crate::cassandra_sys::cass_value_type;
34use crate::cassandra_sys::CassValue as _CassValue;
35use crate::cassandra_sys::CassValueType_;
36use crate::cassandra_sys::CASS_ERROR_LIB_INVALID_VALUE_TYPE;
37use crate::cassandra_sys::CASS_ERROR_LIB_NULL_VALUE;
38use crate::cassandra_sys::CASS_VALUE_TYPE_ASCII;
39use crate::cassandra_sys::CASS_VALUE_TYPE_BIGINT;
40use crate::cassandra_sys::CASS_VALUE_TYPE_BLOB;
41use crate::cassandra_sys::CASS_VALUE_TYPE_BOOLEAN;
42use crate::cassandra_sys::CASS_VALUE_TYPE_COUNTER;
43use crate::cassandra_sys::CASS_VALUE_TYPE_CUSTOM;
44use crate::cassandra_sys::CASS_VALUE_TYPE_DATE;
45use crate::cassandra_sys::CASS_VALUE_TYPE_DECIMAL;
46use crate::cassandra_sys::CASS_VALUE_TYPE_DOUBLE;
47use crate::cassandra_sys::CASS_VALUE_TYPE_DURATION;
48use crate::cassandra_sys::CASS_VALUE_TYPE_FLOAT;
49use crate::cassandra_sys::CASS_VALUE_TYPE_INET;
50use crate::cassandra_sys::CASS_VALUE_TYPE_INT;
51use crate::cassandra_sys::CASS_VALUE_TYPE_LAST_ENTRY;
52use crate::cassandra_sys::CASS_VALUE_TYPE_LIST;
53use crate::cassandra_sys::CASS_VALUE_TYPE_MAP;
54use crate::cassandra_sys::CASS_VALUE_TYPE_SET;
55use crate::cassandra_sys::CASS_VALUE_TYPE_SMALL_INT;
56use crate::cassandra_sys::CASS_VALUE_TYPE_TEXT;
57use crate::cassandra_sys::CASS_VALUE_TYPE_TIME;
58use crate::cassandra_sys::CASS_VALUE_TYPE_TIMESTAMP;
59use crate::cassandra_sys::CASS_VALUE_TYPE_TIMEUUID;
60use crate::cassandra_sys::CASS_VALUE_TYPE_TINY_INT;
61use crate::cassandra_sys::CASS_VALUE_TYPE_TUPLE;
62use crate::cassandra_sys::CASS_VALUE_TYPE_UDT;
63use crate::cassandra_sys::CASS_VALUE_TYPE_UNKNOWN;
64use crate::cassandra_sys::CASS_VALUE_TYPE_UUID;
65use crate::cassandra_sys::CASS_VALUE_TYPE_VARCHAR;
66use crate::cassandra_sys::CASS_VALUE_TYPE_VARINT;
67
68use std::ffi::CString;
69use std::fmt;
70use std::fmt::{Debug, Display, Formatter};
71use std::mem;
72use std::ptr;
73use std::slice;
74use std::str;
75
76/// The type of a Cassandra value.
77#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
78#[allow(missing_docs)] // Meanings are defined in CQL documentation.
79#[allow(non_camel_case_types)] // Names are traditional.
80pub enum ValueType {
81    UNKNOWN,
82    CUSTOM,
83    ASCII,
84    BIGINT,
85    BLOB,
86    BOOLEAN,
87    COUNTER,
88    DECIMAL,
89    DOUBLE,
90    FLOAT,
91    INT,
92    TEXT,
93    TIMESTAMP,
94    UUID,
95    VARCHAR,
96    VARINT,
97    TIMEUUID,
98    INET,
99    DATE,
100    TIME,
101    SMALL_INT,
102    TINY_INT,
103    DURATION,
104    LIST,
105    MAP,
106    SET,
107    UDT,
108    TUPLE,
109}
110
111enhance_nullary_enum!(ValueType, CassValueType_, {
112    (UNKNOWN, CASS_VALUE_TYPE_UNKNOWN, "UNKNOWN"),
113    (CUSTOM, CASS_VALUE_TYPE_CUSTOM, "CUSTOM"),
114    (ASCII, CASS_VALUE_TYPE_ASCII, "ASCII"),
115    (BIGINT, CASS_VALUE_TYPE_BIGINT, "BIGINT"),
116    (BLOB, CASS_VALUE_TYPE_BLOB, "BLOB"),
117    (BOOLEAN, CASS_VALUE_TYPE_BOOLEAN, "BOOLEAN"),
118    (COUNTER, CASS_VALUE_TYPE_COUNTER, "COUNTER"),
119    (DECIMAL, CASS_VALUE_TYPE_DECIMAL, "DECIMAL"),
120    (DOUBLE, CASS_VALUE_TYPE_DOUBLE, "DOUBLE"),
121    (FLOAT, CASS_VALUE_TYPE_FLOAT, "FLOAT"),
122    (INT, CASS_VALUE_TYPE_INT, "INT"),
123    (TEXT, CASS_VALUE_TYPE_TEXT, "TEXT"),
124    (TIMESTAMP, CASS_VALUE_TYPE_TIMESTAMP, "TIMESTAMP"),
125    (UUID, CASS_VALUE_TYPE_UUID, "UUID"),
126    (VARCHAR, CASS_VALUE_TYPE_VARCHAR, "VARCHAR"),
127    (VARINT, CASS_VALUE_TYPE_VARINT, "VARINT"),
128    (TIMEUUID, CASS_VALUE_TYPE_TIMEUUID, "TIMEUUID"),
129    (INET, CASS_VALUE_TYPE_INET, "INET"),
130    (DATE, CASS_VALUE_TYPE_DATE, "DATE"),
131    (TIME, CASS_VALUE_TYPE_TIME, "TIME"),
132    (SMALL_INT, CASS_VALUE_TYPE_SMALL_INT, "SMALL_INT"),
133    (TINY_INT, CASS_VALUE_TYPE_TINY_INT, "TINY_INT"),
134    (DURATION, CASS_VALUE_TYPE_DURATION, "DURATION"),
135    (LIST, CASS_VALUE_TYPE_LIST, "LIST"),
136    (MAP, CASS_VALUE_TYPE_MAP, "MAP"),
137    (SET, CASS_VALUE_TYPE_SET, "SET"),
138    (UDT, CASS_VALUE_TYPE_UDT, "UDT"),
139    (TUPLE, CASS_VALUE_TYPE_TUPLE, "TUPLE"),
140}, omit { CASS_VALUE_TYPE_LAST_ENTRY });
141
142/// A single primitive value or a collection of values.
143pub struct Value(*const _CassValue);
144
145// The underlying C type is read-only so thread-safe.
146unsafe impl Send for Value {}
147unsafe impl Sync for Value {}
148
149impl ProtectedInner<*const _CassValue> for Value {
150    fn inner(&self) -> *const _CassValue {
151        self.0
152    }
153}
154
155impl Protected<*const _CassValue> for Value {
156    fn build(inner: *const _CassValue) -> Self {
157        if inner.is_null() {
158            panic!("Unexpected null pointer")
159        };
160        Value(inner)
161    }
162}
163
164/// Write a set iterator to a formatter.
165pub(crate) fn write_set<F>(f: &mut Formatter, set: Result<SetIterator>, writer: F) -> fmt::Result
166where
167    F: Fn(&mut Formatter, Value) -> fmt::Result,
168{
169    write!(f, "[")?;
170    match set {
171        Err(_) => write!(f, "<error>")?,
172        Ok(iter) => {
173            for item in iter {
174                writer(f, item)?
175            }
176        }
177    }
178    write!(f, "]")?;
179    Ok(())
180}
181
182/// Write a map iterator to a formatter.
183pub(crate) fn write_map<F>(f: &mut Formatter, set: Result<MapIterator>, writer: F) -> fmt::Result
184where
185    F: Fn(&mut Formatter, Value, Value) -> fmt::Result,
186{
187    write!(f, "{{")?;
188    match set {
189        Err(_) => write!(f, "<error>")?,
190        Ok(iter) => {
191            for item in iter {
192                writer(f, item.0, item.1)?
193            }
194        }
195    }
196    write!(f, "}}")?;
197    Ok(())
198}
199
200pub(crate) fn write_value<T, F>(f: &mut Formatter, v: Result<T>, writer: F) -> fmt::Result
201where
202    F: Fn(&mut Formatter, T) -> fmt::Result,
203{
204    match v {
205        Err(_) => write!(f, "<error>"),
206        Ok(v) => writer(f, v),
207    }
208}
209
210impl Debug for Value {
211    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
212        if self.is_null() {
213            Ok(())
214        } else {
215            match self.get_type() {
216                ValueType::UNKNOWN => write!(f, "<unknown>"),
217                ValueType::CUSTOM => write!(f, "<custom>"),
218                ValueType::ASCII | ValueType::TEXT | ValueType::VARCHAR => {
219                    write_value(f, self.get_string(), |f, v| write!(f, "{:?}", v))
220                }
221                ValueType::DECIMAL => write_value(f, self.get_bytes(), |f, v| write!(f, "{:?}", v)),
222                ValueType::COUNTER => write_value(f, self.get_i64(), |f, v| write!(f, "{:?}", v)),
223                ValueType::BIGINT => write_value(f, self.get_i64(), |f, v| write!(f, "{:?}", v)),
224                ValueType::DATE => write_value(f, self.get_string(), |f, v| write!(f, "{:?}", v)),
225                ValueType::TIME => write_value(f, self.get_string(), |f, v| write!(f, "{:?}", v)),
226                ValueType::VARINT => write_value(f, self.get_bytes(), |f, v| write!(f, "{:?}", v)),
227                ValueType::BOOLEAN => write_value(f, self.get_bool(), |f, v| write!(f, "{:?}", v)),
228                ValueType::DOUBLE => write_value(f, self.get_f64(), |f, v| write!(f, "{:?}", v)),
229                ValueType::FLOAT => write_value(f, self.get_f32(), |f, v| write!(f, "{:?}", v)),
230                ValueType::BLOB => write_value(f, self.get_bytes(), |f, v| write!(f, "{:?}", v)),
231                ValueType::INT => write_value(f, self.get_i32(), |f, v| write!(f, "{:?}", v)),
232                ValueType::SMALL_INT => write_value(f, self.get_i16(), |f, v| write!(f, "{:?}", v)),
233                ValueType::TINY_INT => write_value(f, self.get_i8(), |f, v| write!(f, "{:?}", v)),
234                ValueType::DURATION => write_value(f, self.get_i32(), |f, v| write!(f, "{:?}", v)),
235                ValueType::INET => write_value(f, self.get_inet(), |f, v| write!(f, "{:?}", v)),
236                ValueType::TIMESTAMP => write_value(f, self.get_i64(), |f, v| write!(f, "{:?}", v)),
237                ValueType::TIMEUUID => {
238                    write_value(f, self.get_uuid(), |f, v| write!(f, "TIMEUUID: {}", v))
239                }
240                ValueType::UUID => write_value(f, self.get_uuid(), |f, v| write!(f, "UUID: {}", v)),
241                ValueType::SET | ValueType::LIST => {
242                    write_set(f, self.get_set(), |f, i| write!(f, "{:?}, ", i))
243                }
244                ValueType::MAP => write_map(f, self.get_map(), |f, k, v| {
245                    write!(f, "{:?} => {:?}, ", k, v)
246                }),
247                ValueType::UDT => write!(f, "<udt>"),
248                ValueType::TUPLE => write_set(f, self.get_set(), |f, i| write!(f, "{:?}, ", i)),
249            }
250        }
251    }
252}
253
254impl Display for Value {
255    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
256        if self.is_null() {
257            Ok(())
258        } else {
259            match self.get_type() {
260                ValueType::UNKNOWN => write!(f, "{}", "unknown"),
261                ValueType::CUSTOM => write!(f, "{}", "custom"),
262                ValueType::ASCII | ValueType::TEXT | ValueType::VARCHAR => {
263                    write_value(f, self.get_string(), |f, v| write!(f, "{}", v))
264                }
265                ValueType::DECIMAL => {
266                    write_value(f, self.get_bytes(), |f, v| write!(f, "DECIMAL:{:?}", v))
267                }
268                ValueType::COUNTER => write_value(f, self.get_i64(), |f, v| write!(f, "{}", v)),
269                ValueType::BIGINT => write_value(f, self.get_i64(), |f, v| write!(f, "{}", v)),
270                ValueType::DATE => write_value(f, self.get_string(), |f, v| write!(f, "{}", v)),
271                ValueType::TIME => write_value(f, self.get_string(), |f, v| write!(f, "{}", v)),
272                ValueType::VARINT => {
273                    write_value(f, self.get_bytes(), |f, v| write!(f, "VARINT:{:?}", v))
274                }
275                ValueType::BOOLEAN => write_value(f, self.get_bool(), |f, v| write!(f, "{}", v)),
276                ValueType::DOUBLE => write_value(f, self.get_f64(), |f, v| write!(f, "{}", v)),
277                ValueType::FLOAT => write_value(f, self.get_f32(), |f, v| write!(f, "{}", v)),
278                ValueType::BLOB => {
279                    write_value(f, self.get_bytes(), |f, v| write!(f, "BLOB:{:?}", v))
280                }
281                ValueType::INT => write_value(f, self.get_i32(), |f, v| write!(f, "{}", v)),
282                ValueType::SMALL_INT => write_value(f, self.get_i16(), |f, v| write!(f, "{}", v)),
283                ValueType::TINY_INT => write_value(f, self.get_i8(), |f, v| write!(f, "{}", v)),
284                ValueType::DURATION => write_value(f, self.get_i32(), |f, v| write!(f, "{:?}", v)),
285                ValueType::INET => {
286                    write_value(f, self.get_inet(), |f, v| write!(f, "INET:{:?}", v))
287                }
288                ValueType::TIMESTAMP => write_value(f, self.get_i64(), |f, v| write!(f, "{}", v)),
289                ValueType::TIMEUUID => {
290                    write_value(f, self.get_uuid(), |f, v| write!(f, "TIMEUUID:{}", v))
291                }
292                ValueType::UUID => write_value(f, self.get_uuid(), |f, v| write!(f, "UUID:{}", v)),
293                ValueType::SET | ValueType::LIST => {
294                    write_set(f, self.get_set(), |f, i| write!(f, "{}, ", i))
295                }
296                ValueType::MAP => {
297                    write_map(f, self.get_map(), |f, k, v| write!(f, "{} => {}, ", k, v))
298                }
299                ValueType::UDT => write!(f, "<udt>"),
300                ValueType::TUPLE => write_set(f, self.get_set(), |f, i| write!(f, "{}, ", i)),
301            }
302        }
303    }
304}
305
306impl Value {
307    /// Get the raw bytes of this Cassandra value.
308    pub fn get_bytes(&self) -> Result<&[u8]> {
309        unsafe {
310            let mut output = mem::zeroed();
311            let mut output_size = mem::zeroed();
312            let result = cass_value_get_bytes(self.0, &mut output, &mut output_size);
313            // raw2utf8(output, output_size).unwrap()
314            let slice = slice::from_raw_parts(output, output_size as usize);
315            result.to_result(slice)
316        }
317    }
318    // pub fn get_decimal<'a>(&'a self, mut output: String) ->
319    // Result<String,CassError> {unsafe{
320    // CassError::build(cass_value_get_decimal(self.0,&mut
321    // output)).wrap(output)
322    //    }}
323
324    /// Get the type of this Cassandra value
325    pub fn get_type(&self) -> ValueType {
326        unsafe { ValueType::build(cass_value_type(self.0)) }
327    }
328
329    /// Get the data type of this Cassandra value
330    pub fn data_type(&self) -> ConstDataType {
331        unsafe { ConstDataType::build(cass_value_data_type(self.0)) }
332    }
333
334    /// Returns true if a specified value is null.
335    pub fn is_null(&self) -> bool {
336        unsafe { cass_value_is_null(self.0) == cass_true }
337    }
338
339    /// Returns true if a specified value is a collection.
340    pub fn is_collection(&self) -> bool {
341        unsafe { cass_value_is_collection(self.0) == cass_true }
342    }
343
344    //    pub fn item_count(&self) -> u64 {
345    //        unsafe { cass_value_item_count(self.0) }
346    //    }
347
348    // 	///Get the primary sub-type for a collection. This returns the sub-type for a
349    // 	///list or set and the key type for a map.
350    //    pub fn primary_sub_type(&self) -> ValueType {
351    //        unsafe { ValueType::build(cass_value_primary_sub_type(self.0)).unwrap() }
352    //    }
353
354    // 	///Get the secondary sub-type for a collection. This returns the value type for a map.
355    //    pub fn secondary_sub_type(&self) -> ValueType {
356    //        unsafe { ValueType::build(cass_value_secondary_sub_type(self.0)).unwrap() }
357    //    }
358
359    /// Gets this value as a set iterator.
360    pub fn get_set(&self) -> Result<SetIterator> {
361        unsafe {
362            match self.get_type() {
363                ValueType::SET | ValueType::LIST | ValueType::TUPLE => {
364                    let iter = cass_iterator_from_collection(self.0);
365                    if iter.is_null() {
366                        // No iterator, probably because this set is_null. Complain.
367                        Err(CASS_ERROR_LIB_NULL_VALUE.to_error())
368                    } else {
369                        Ok(SetIterator::build(iter))
370                    }
371                }
372                _ => Err(CASS_ERROR_LIB_INVALID_VALUE_TYPE.to_error()),
373            }
374        }
375    }
376
377    /// Gets this value as a map iterator.
378    pub fn get_map(&self) -> Result<MapIterator> {
379        unsafe {
380            match self.get_type() {
381                ValueType::MAP => {
382                    let iter = cass_iterator_from_map(self.0);
383                    if iter.is_null() {
384                        // No iterator, probably because this map is_null. Complain.
385                        Err(CASS_ERROR_LIB_NULL_VALUE.to_error())
386                    } else {
387                        Ok(MapIterator::build(iter))
388                    }
389                }
390                _ => Err(CASS_ERROR_LIB_INVALID_VALUE_TYPE.to_error()),
391            }
392        }
393    }
394
395    /// Gets an iterator over the fields of the user type in this column or errors if you ask for the wrong type
396    pub fn get_user_type(&self) -> Result<UserTypeIterator> {
397        unsafe {
398            match self.get_type() {
399                ValueType::UDT => {
400                    let iter = cass_iterator_fields_from_user_type(self.0);
401                    if iter.is_null() {
402                        // No iterator, probably because this user_type field is null. Complain.
403                        Err(CASS_ERROR_LIB_NULL_VALUE.to_error())
404                    } else {
405                        Ok(UserTypeIterator::build(iter))
406                    }
407                }
408                _ => Err(CASS_ERROR_LIB_INVALID_VALUE_TYPE.to_error()),
409            }
410        }
411    }
412
413    /// Get this value as a string slice
414    pub fn get_str(&self) -> Result<&str> {
415        unsafe {
416            let mut message_ptr = mem::zeroed();
417            let mut message_length = mem::zeroed();
418            cass_value_get_string(self.0, &mut message_ptr, &mut message_length)
419                .to_result(())
420                .and_then(|_| {
421                    let slice =
422                        slice::from_raw_parts(message_ptr as *const u8, message_length as usize);
423                    Ok(str::from_utf8(slice)?)
424                })
425        }
426    }
427
428    /// Get this value as a string
429    pub fn get_string(&self) -> Result<String> {
430        self.get_str().map(str::to_string)
431    }
432
433    /// Get this value as an Inet
434    pub fn get_inet(&self) -> Result<Inet> {
435        unsafe {
436            let mut inet = mem::zeroed();
437            cass_value_get_inet(self.0, &mut inet).to_result(Inet::build(inet))
438        }
439    }
440
441    /// Get this value as an i32
442    pub fn get_i32(&self) -> Result<i32> {
443        unsafe {
444            let mut output = mem::zeroed();
445            cass_value_get_int32(self.0, &mut output).to_result(output)
446        }
447    }
448
449    /// Get this value as a u32
450    pub fn get_u32(&self) -> Result<u32> {
451        unsafe {
452            let mut output = mem::zeroed();
453            cass_value_get_uint32(self.0, &mut output).to_result(output)
454        }
455    }
456
457    /// Get this value as an i16
458    pub fn get_i16(&self) -> Result<i16> {
459        unsafe {
460            let mut output = mem::zeroed();
461            cass_value_get_int16(self.0, &mut output).to_result(output)
462        }
463    }
464
465    /// Get this value as an i8
466    pub fn get_i8(&self) -> Result<i8> {
467        unsafe {
468            let mut output = mem::zeroed();
469            cass_value_get_int8(self.0, &mut output).to_result(output)
470        }
471    }
472
473    /// Get this value as an i64
474    pub fn get_i64(&self) -> Result<i64> {
475        unsafe {
476            let mut output = mem::zeroed();
477            cass_value_get_int64(self.0, &mut output).to_result(output)
478        }
479    }
480
481    /// Get this value as a float
482    pub fn get_f32(&self) -> Result<f32> {
483        unsafe {
484            let mut output = mem::zeroed();
485            cass_value_get_float(self.0, &mut output).to_result(output)
486        }
487    }
488
489    /// Get this value as a double
490    pub fn get_f64(&self) -> Result<f64> {
491        unsafe {
492            let mut output = mem::zeroed();
493            cass_value_get_double(self.0, &mut output).to_result(output)
494        }
495    }
496
497    /// Get this value asa boolean
498    pub fn get_bool(&self) -> Result<bool> {
499        unsafe {
500            let mut output = mem::zeroed();
501            cass_value_get_bool(self.0, &mut output).to_result(output == cass_true)
502        }
503    }
504
505    /// Get this value as a UUID
506    pub fn get_uuid(&self) -> Result<Uuid> {
507        unsafe {
508            let mut uuid = mem::zeroed();
509            cass_value_get_uuid(self.0, &mut uuid).to_result(Uuid::build(uuid))
510        }
511    }
512}