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