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#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
55#[allow(missing_docs)] #[allow(non_camel_case_types)] pub 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
119pub struct Value<'a>(*const _CassValue, PhantomData<&'a _CassValue>);
123
124unsafe 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
144pub(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
162pub(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 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 pub fn get_type(&self) -> ValueType {
302 unsafe { ValueType::build(cass_value_type(self.0)) }
303 }
304
305 pub fn data_type(&self) -> ConstDataType<'a> {
307 unsafe { ConstDataType::build(cass_value_data_type(self.0)) }
308 }
309
310 pub fn is_null(&self) -> bool {
312 unsafe { cass_value_is_null(self.0) == cass_true }
313 }
314
315 pub fn is_collection(&self) -> bool {
317 unsafe { cass_value_is_collection(self.0) == cass_true }
318 }
319
320 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 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 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 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 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 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 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 pub fn get_string(&self) -> Result<String> {
405 self.get_str().map(str::to_string)
406 }
407
408 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 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 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 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 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 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 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 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 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 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 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}