use cassandra::data_type::ConstDataType;
use cassandra::error::CassError;
use cassandra::inet::Inet;
use cassandra::iterator::MapIterator;
use cassandra::iterator::SetIterator;
use cassandra::util::Protected;
use cassandra::uuid::Uuid;
use cassandra_sys::CASS_OK;
use cassandra_sys::CASS_ERROR_LIB_INVALID_VALUE_TYPE;
use cassandra_sys::CASS_VALUE_TYPE_ASCII;
use cassandra_sys::CASS_VALUE_TYPE_BIGINT;
use cassandra_sys::CASS_VALUE_TYPE_BLOB;
use cassandra_sys::CASS_VALUE_TYPE_BOOLEAN;
use cassandra_sys::CASS_VALUE_TYPE_COUNTER;
use cassandra_sys::CASS_VALUE_TYPE_CUSTOM;
use cassandra_sys::CASS_VALUE_TYPE_DATE;
use cassandra_sys::CASS_VALUE_TYPE_DECIMAL;
use cassandra_sys::CASS_VALUE_TYPE_DOUBLE;
use cassandra_sys::CASS_VALUE_TYPE_FLOAT;
use cassandra_sys::CASS_VALUE_TYPE_INET;
use cassandra_sys::CASS_VALUE_TYPE_INT;
use cassandra_sys::CASS_VALUE_TYPE_LAST_ENTRY;
use cassandra_sys::CASS_VALUE_TYPE_LIST;
use cassandra_sys::CASS_VALUE_TYPE_MAP;
use cassandra_sys::CASS_VALUE_TYPE_SET;
use cassandra_sys::CASS_VALUE_TYPE_SMALL_INT;
use cassandra_sys::CASS_VALUE_TYPE_TEXT;
use cassandra_sys::CASS_VALUE_TYPE_TIME;
use cassandra_sys::CASS_VALUE_TYPE_TIMESTAMP;
use cassandra_sys::CASS_VALUE_TYPE_TIMEUUID;
use cassandra_sys::CASS_VALUE_TYPE_TINY_INT;
use cassandra_sys::CASS_VALUE_TYPE_TUPLE;
use cassandra_sys::CASS_VALUE_TYPE_UDT;
use cassandra_sys::CASS_VALUE_TYPE_UNKNOWN;
use cassandra_sys::CASS_VALUE_TYPE_UUID;
use cassandra_sys::CASS_VALUE_TYPE_VARCHAR;
use cassandra_sys::CASS_VALUE_TYPE_VARINT;
use cassandra_sys::CassValue as _CassValue;
use cassandra_sys::CassValueType as _CassValueType;
#[allow(unused_imports)]
use cassandra_sys::cass_collection_append_decimal;
use cassandra_sys::cass_iterator_from_collection;
use cassandra_sys::cass_iterator_from_map;
use cassandra_sys::cass_true;
use cassandra_sys::cass_value_data_type;
use cassandra_sys::cass_value_get_bool;
use cassandra_sys::cass_value_get_bytes;
use cassandra_sys::cass_value_get_double;
use cassandra_sys::cass_value_get_float;
use cassandra_sys::cass_value_get_inet;
use cassandra_sys::cass_value_get_int16;
use cassandra_sys::cass_value_get_int32;
use cassandra_sys::cass_value_get_int64;
use cassandra_sys::cass_value_get_int8;
use cassandra_sys::cass_value_get_string;
use cassandra_sys::cass_value_get_uuid;
use cassandra_sys::cass_value_is_collection;
use cassandra_sys::cass_value_is_null;
#[allow(unused_imports)]
use cassandra_sys::cass_value_item_count;
#[allow(unused_imports)]
use cassandra_sys::cass_value_primary_sub_type;
#[allow(unused_imports)]
use cassandra_sys::cass_value_secondary_sub_type;
use cassandra_sys::cass_value_type;
use errors::*;
use std::ffi::CString;
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::mem;
use std::ptr;
use std::slice;
use std::str;
pub struct Value(*const _CassValue);
impl Protected<*const _CassValue> for Value {
fn inner(&self) -> *const _CassValue { self.0 }
fn build(inner: *const _CassValue) -> Self { Value(inner) }
}
#[derive(Debug)]
#[allow(missing_docs)]
pub struct ValueType(_CassValueType);
impl ValueType {
#[allow(missing_docs)]
pub fn build(typ: _CassValueType) -> Self { ValueType(typ) }
}
impl Protected<_CassValueType> for ValueType {
fn inner(&self) -> _CassValueType { self.0 }
fn build(inner: _CassValueType) -> Self { ValueType(inner) }
}
impl Debug for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.is_null() {
Ok(())
} else {
match self.get_type().0 {
CASS_VALUE_TYPE_UNKNOWN => write!(f, "{:?}", "unknown"),
CASS_VALUE_TYPE_CUSTOM => write!(f, "{:?}", "custom"),
CASS_VALUE_TYPE_ASCII |
CASS_VALUE_TYPE_TEXT |
CASS_VALUE_TYPE_VARCHAR => write!(f, "{:?}", self.get_string().unwrap()),
CASS_VALUE_TYPE_DECIMAL => write!(f, "{:?}", self.get_bytes().unwrap()),
CASS_VALUE_TYPE_COUNTER => write!(f, "{:?}", self.get_i64().unwrap()),
CASS_VALUE_TYPE_BIGINT => write!(f, "{:?}", self.get_i64().unwrap()),
CASS_VALUE_TYPE_DATE => write!(f, "{:?}", self.get_string().unwrap()),
CASS_VALUE_TYPE_TIME => write!(f, "{:?}", self.get_string().unwrap()),
CASS_VALUE_TYPE_VARINT => write!(f, "{:?}", self.get_bytes().unwrap()),
CASS_VALUE_TYPE_BOOLEAN => write!(f, "{:?}", self.get_bool().unwrap()),
CASS_VALUE_TYPE_DOUBLE => write!(f, "{:?}", self.get_dbl().unwrap()),
CASS_VALUE_TYPE_FLOAT => write!(f, "{:?}", self.get_flt().unwrap()),
CASS_VALUE_TYPE_BLOB => write!(f, "{:?}", self.get_bytes().unwrap()),
CASS_VALUE_TYPE_INT => write!(f, "{:?}", self.get_i32().unwrap()),
CASS_VALUE_TYPE_SMALL_INT => write!(f, "{:?}", self.get_i16().unwrap()),
CASS_VALUE_TYPE_TINY_INT => write!(f, "{:?}", self.get_i8().unwrap()),
CASS_VALUE_TYPE_INET => write!(f, "{:?}", self.get_inet().unwrap()),
CASS_VALUE_TYPE_TIMESTAMP => write!(f, "{:?}", self.get_i64().unwrap()),
CASS_VALUE_TYPE_TIMEUUID => write!(f, "TIMEUUID: {}", self.get_uuid().unwrap()),
CASS_VALUE_TYPE_LAST_ENTRY => unimplemented!(),
CASS_VALUE_TYPE_UUID => write!(f, "UUID: {}", self.get_uuid().unwrap()),
CASS_VALUE_TYPE_SET |
CASS_VALUE_TYPE_LIST => {
write!(f, "[")?;
for item in self.get_set().expect("set must be a set") {
write!(f, "SET {:?} ", item)?
}
write!(f, "]")?;
Ok(())
}
CASS_VALUE_TYPE_MAP => {
for item in self.get_map().expect("map must be a map") {
write!(f, "MAP {:?}:{:?}", item.0, item.1)?
}
Ok(())
}
CASS_VALUE_TYPE_UDT => {
debug!("unimplemented for udt!");
Ok(())
}
CASS_VALUE_TYPE_TUPLE => {
debug!("unimplemented for tuple!");
Ok(())
}
}
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.is_null() {
Ok(())
} else {
match self.get_type().0 {
CASS_VALUE_TYPE_UNKNOWN => write!(f, "{}", "unknown"),
CASS_VALUE_TYPE_CUSTOM => write!(f, "{}", "custom"),
CASS_VALUE_TYPE_ASCII => write!(f, "{}", self.get_string().unwrap()),
CASS_VALUE_TYPE_BIGINT => write!(f, "{}", self.get_i64().unwrap()),
CASS_VALUE_TYPE_VARCHAR => write!(f, "{}", self.get_string().unwrap()),
CASS_VALUE_TYPE_BOOLEAN => write!(f, "{}", self.get_bool().unwrap()),
CASS_VALUE_TYPE_DOUBLE => write!(f, "{}", self.get_dbl().unwrap()),
CASS_VALUE_TYPE_FLOAT => write!(f, "{}", self.get_flt().unwrap()),
CASS_VALUE_TYPE_INT => write!(f, "{}", self.get_i32().unwrap()),
CASS_VALUE_TYPE_TIMEUUID => write!(f, "TIMEUUID: {}", self.get_uuid().unwrap()),
CASS_VALUE_TYPE_SET => {
write!(f, "[")?;
for item in self.get_set().expect("set must be a set") {
write!(f, "{} ", item)?
}
write!(f, "]")?;
Ok(())
}
CASS_VALUE_TYPE_MAP => {
for item in self.get_map().expect("map must be a map") {
write!(f, "MAP {}:{}", item.0, item.1)?
}
Ok(())
}
_ => write!(f, "unknown type"),
}
}
}
}
impl Value {
#[allow(cast_possible_truncation)]
pub fn get_bytes(&self) -> Result<&[u8]> {
unsafe {
let mut output = mem::zeroed();
let mut output_size = mem::zeroed();
let result = cass_value_get_bytes(self.0, &mut output, &mut output_size);
let slice = slice::from_raw_parts(output, output_size as usize);
result.to_result(slice).chain_err(|| "")
}
}
pub fn get_type(&self) -> ValueType { unsafe { ValueType(cass_value_type(self.0)) } }
pub fn data_type(&self) -> ConstDataType { unsafe { ConstDataType(cass_value_data_type(self.0)) } }
pub fn is_null(&self) -> bool { unsafe { cass_value_is_null(self.0) == cass_true } }
pub fn is_collection(&self) -> bool { unsafe { cass_value_is_collection(self.0) == cass_true } }
pub fn get_set(&self) -> Result<SetIterator> {
unsafe {
match self.get_type().0 {
CASS_VALUE_TYPE_SET => Ok(SetIterator::build(cass_iterator_from_collection(self.0))),
_ => Err("LIB_INVALID_VALUE_TYPE".into()),
}
}
}
pub fn get_map(&self) -> Result<MapIterator> {
unsafe {
match self.get_type().0 {
CASS_VALUE_TYPE_MAP => Ok(MapIterator::build(cass_iterator_from_map(self.0))),
_ => Err("LIB_INVALID_VALUE_TYPE".into()),
}
}
}
#[allow(cast_possible_truncation)]
pub fn get_string(&self) -> Result<&str> {
unsafe {
let mut message_ptr = ptr::null();
let mut message_length = 0;
match cass_value_get_string(self.0, &mut message_ptr, &mut (message_length)) {
CASS_OK => {
let slice = slice::from_raw_parts(message_ptr as *const u8, message_length as usize);
str::from_utf8(slice).chain_err(|| "")
},
err => Err(err).chain_err(|| ""),
}
}
}
pub fn get_inet(&self) -> Result<Inet> {
unsafe {
let output: Inet = mem::zeroed();
cass_value_get_inet(self.0, &mut Inet::inner(&output))
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_i32(&self) -> Result<i32> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_int32(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_i16(&self) -> Result<i16> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_int16(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_i8(&self) -> Result<i8> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_int8(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_i64(&self) -> Result<i64> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_int64(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_flt(&self) -> Result<f32> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_float(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_dbl(&self) -> Result<f64> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_double(self.0, &mut output)
.to_result(output)
.chain_err(|| "")
}
}
pub fn get_bool(&self) -> Result<bool> {
unsafe {
let mut output = mem::zeroed();
cass_value_get_bool(self.0, &mut output)
.to_result(output == cass_true)
.chain_err(|| "")
}
}
pub fn get_uuid(&self) -> Result<Uuid> {
unsafe {
let mut uuid = mem::zeroed();
cass_value_get_uuid(self.0, &mut uuid)
.to_result(Uuid::build(uuid))
.chain_err(|| "")
}
}
}