cassandra-cpp 0.8.2

A Cassandra CQL driver, built on top of the DataStax C++ driver for performance and functionality.
Documentation
#![macro_use]
// use cassandra_sys;

use cassandra::consistency::Consistency;
use cassandra::util::Protected;
use cassandra::write_type::WriteType;

use cassandra_sys::CASS_OK;
use cassandra_sys::CassError as _CassError;

use cassandra_sys::CassErrorResult as _CassErrorResult;
use cassandra_sys::cass_error_desc;
use cassandra_sys::cass_error_num_arg_types;
use cassandra_sys::cass_error_result_arg_type;
use cassandra_sys::cass_error_result_code;
use cassandra_sys::cass_error_result_consistency;
use cassandra_sys::cass_error_result_data_present;
use cassandra_sys::cass_error_result_free;
use cassandra_sys::cass_error_result_function;
use cassandra_sys::cass_error_result_keyspace;
use cassandra_sys::cass_error_result_num_failures;
use cassandra_sys::cass_error_result_responses_received;
use cassandra_sys::cass_error_result_responses_required;
use cassandra_sys::cass_error_result_table;
use cassandra_sys::cass_error_result_write_type;
use errors::*;
use errors::*;
use std::{fmt, mem, slice, str};
use std::error::Error as IError;
// use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt::{Debug, Display, Formatter};
use std::os::raw::c_char;

// Simple and robust error handling with error-chain!
// Use this as a template for new projects.

// #[macro_export]
// macro_rules! err_wrap {
//    ( $s:expr,$x:expr ) => {match $x {
//                CASS_OK => Ok($s),
//                err => Err(Error::from(err.into()))
//            }
//    }
// }

error_chain! {
       // Automatic conversions between this error chain and other
    // error types not defined by the `error_chain!`. These will be
    // wrapped in a new error with, in this case, the
    // `ErrorKind::Temp` variant. The description and cause will
    // forward to the description and cause of the original error.
    //
    // Optionally, some attributes can be added to a variant.
    //
    // This section can be empty.
    foreign_links {
        Fmt(::std::fmt::Error);
        Io(::std::io::Error) #[cfg(unix)];
        Null(::std::ffi::NulError);
        Cass(_CassError);
        Utf8(::std::str::Utf8Error);
    }

    // Define additional `ErrorKind` variants. The syntax here is
    // the same as `quick_error!`, but the `from()` and `cause()`
    // syntax is not supported.
    errors {
        CassError(t: String) {
            //description("invalid toolchain name")
            //display("invalid toolchain name: '{}'", t)
        }
    }
}



/// An error returned by Cassandra or the driver
pub struct CassError(_CassError);

// ///An error generated by the C++ driver
// pub struct CassLibError {
//    err: _CassError,
//    msg: String,
// }

impl From<_CassError> for CassError {
    fn from(err:_CassError) -> CassError {
        CassError(err)
    }
}

// ///An error signaled by the server and sent to the client over CQL transport
// pub struct CassServerError(_CassError);
// ///An error signaled by the client-linked SSL library
// pub struct CassSslError(_CassError);

impl ::std::error::Error for CassError {
    fn description(&self) -> &str {
        unimplemented!()
        // self.desc()
        // let c_buf: *const i8 = self.desc();
        // let buf: &[u8] = unsafe { CStr::from_ptr(c_buf).to_bytes() };
        // from_utf8(buf).unwrap()
    }
}

// impl From<AddrParseError> for CassError {
//    fn from(err: AddrParseError) -> CassError {
//        CassError::Rust(CassRustError::BadAddress(err))
//    }
// }

// impl From<NulError> for CassError {
//    fn from(err: NulError) -> CassError {
//        CassError::Rust(CassRustError::NulInString(err))
//    }
// }

impl Display for CassError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
        //        let c_buf: *const i8 = self.desc();
        //        let buf: &[u8] = unsafe { CStr::from_ptr(c_buf).to_bytes() };
        //        match str::from_utf8(buf) {
        //            Ok(str_slice) => write!(f, "{}", str_slice),
        //            Err(err) => panic!("unreachable? {:?}", err),
        //        }
    }
}
//
impl Debug for CassError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
        //        let c_buf: *const i8 = self.desc();
        //        let buf: &[u8] = unsafe { CStr::from_ptr(c_buf).to_bytes() };
        //        match str::from_utf8(buf) {
        //            Ok(str_slice) => write!(f, "{:?}", str_slice),
        //            Err(err) => panic!("unreachable? {:?}", err),
        //        }
    }
}

// impl From<NulError> for CassError {
//    fn from(err: NulError) -> CassError {
//        CliError::Io(err)
//    }
// }

// impl CassError {
//   /// Takes an upstream error and wraps it into the appropriate CassError
//    pub fn wrap<T>(self, wrappee: T) -> Result<T> {
//        match self.0 {
//            CASS_OK => Ok(wrappee),
//            err => Err(Error::from(err.into())),
//        }
//    }
//    //
// }
/// An error result of a request
#[derive(Debug)]
pub struct CassErrorResult(*const _CassErrorResult);

impl Protected<*const _CassErrorResult> for CassErrorResult {
    fn inner(&self) -> *const _CassErrorResult { self.0 }
    fn build(inner: *const _CassErrorResult) -> Self { CassErrorResult(inner) }
}

// impl CassErrorResult {
//    /// Gets error code for the error result. This error code will always
//    /// have an server error source.
//    pub fn result_code(&self) -> u32 { unsafe { cass_error_result_code(self.0) as u32 } }
//
//    /// Gets consistency that triggered the error result of the
//    /// following types:
//    ///
//    /// <ul>
//    ///  <li>CASS_ERROR_SERVER_READ_TIMEOUT</li>
//    ///  <li>CASS_ERROR_SERVER_WRITE_TIMEOUT</li>
//    ///  <li>CASS_ERROR_SERVER_READ_FAILURE</li>
//    ///  <li>CASS_ERROR_SERVER_WRITE_FAILURE</li>
//    ///  <li>CASS_ERROR_SERVER_UNAVAILABLE</li>
//    /// </ul>
//    pub fn result_consistency(&self) -> Consistency {
//        unsafe { Consistency::build(cass_error_result_consistency(self.0)) }
//    }
//
//    /// Gets the actual number of received responses, received acknowledgments
//    /// or alive nodes for following error result types, respectively:
//    ///
//    /// <ul>
//    ///  <li>CASS_ERROR_SERVER_READ_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_READ_FAILURE</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_FAILURE</li>
//    ///   <li>CASS_ERROR_SERVER_UNAVAILABLE</li>
//    /// </ul>
//    pub fn responses_received(&self) -> i32 { unsafe { cass_error_result_responses_received(self.0) } }
//
//    /// Gets required responses, required acknowledgments or required alive nodes
//    /// needed to successfully complete the request for following error result types,
//    /// respectively:
//    ///
//    /// <ul>
//    ///  <li>CASS_ERROR_SERVER_READ_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_READ_FAILURE</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_FAILURE</li>
//    ///   <li>CASS_ERROR_SERVER_UNAVAILABLE</li>
//    /// </ul>
//    pub fn responses_required(&self) -> i32 { unsafe { cass_error_result_responses_required(self.0) } }
//
//    /// Gets the number of nodes that experienced failures for the following error types:
//    ///
//    /// <ul>
//    ///   <li>CASS_ERROR_SERVER_READ_FAILURE</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_FAILURE</li>
//    /// </ul>
//    pub fn num_failures(&self) -> i32 { unsafe { cass_error_result_num_failures(self.0) } }
//
//    /// Determines whether the actual data was present in the responses from the
//    /// replicas for the following error result types:
//    ///
//    /// <ul>
//    ///   <li>CASS_ERROR_SERVER_READ_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_READ_FAILURE</li>
//    /// </ul>
//    pub fn data_present(&self) -> bool { unsafe { cass_error_result_data_present(self.0) as i32 > 0 } }
//
//
//    /// Gets the write type of a request for the following error result types:
//    ///
//    /// <ul>
//    ///   <li>CASS_ERROR_SERVER_WRITE_TIMEOUT</li>
//    ///   <li>CASS_ERROR_SERVER_WRITE_FAILURE</li>
//    /// </ul>
//    pub fn write_type(&self) -> WriteType { unsafe { WriteType(cass_error_result_write_type(self.0)) } }
//
//    /// Gets the affected keyspace for the following error result types:
//    ///
//    /// <ul>
//    ///   <li>CASS_ERROR_SERVER_ALREADY_EXISTS</li>
//    ///   <li>CASS_ERROR_SERVER_FUNCTION_FAILURE</li>
//    /// </ul>
//    #[allow(cast_possible_truncation)]
//    pub fn keyspace(&self) -> String {
//        unsafe {
//            let mut name = mem::zeroed();
//            let mut length = mem::zeroed();
//            match cass_error_result_keyspace(self.0, &mut name, &mut length) {
//                CASS_OK => {
//                    let slice = slice::from_raw_parts(name as *const u8, length as usize);
//                    str::from_utf8(slice).expect("must be utf8").to_owned()
//                }
//                err => panic!("impossible: {:?}", err),
//            }
//        }
//    }
//
//    /// Gets the affected table for the already exists error
//    /// (CASS_ERROR_SERVER_ALREADY_EXISTS) result type.
//    #[allow(cast_possible_truncation)]
//    pub fn table(&self) -> String {
//        unsafe {
//            let mut name = mem::zeroed();
//            let mut length = mem::zeroed();
//            match cass_error_result_table(self.0, &mut name, &mut length) {
//                CASS_OK => {
//                    let slice = slice::from_raw_parts(name as *const u8, length as usize);
//                    str::from_utf8(slice).expect("must be utf8").to_owned()
//                }
//                err => panic!("impossible: {:?}", err),
//            }
//        }
//    }
//
//    /// Gets the affected function for the function failure error
//    /// (CASS_ERROR_SERVER_FUNCTION_FAILURE) result type.
//    #[allow(cast_possible_truncation)]
//    pub fn function(&self) -> String {
//        unsafe {
//            let mut name = mem::zeroed();
//            let mut length = mem::zeroed();
//            match cass_error_result_function(self.0, &mut name, &mut length) {
//                CASS_OK => {
//                    let slice = slice::from_raw_parts(name as *const u8, length as usize);
//                    str::from_utf8(slice).expect("must be utf8").to_owned()
//                }
//                err => panic!("impossible: {:?}", err),
//            }
//        }
//    }
//
//    /// Gets the number of argument types for the function failure error
//    /// (CASS_ERROR_SERVER_FUNCTION_FAILURE) result type.
//    pub fn num_arg_types(error_result: CassErrorResult) -> usize { unsafe { cass_error_num_arg_types(error_result.0) } }
//
//    /// Gets the argument type at the specified index for the function failure
//    /// error (CASS_ERROR_SERVER_FUNCTION_FAILURE) result type.
//    pub fn arg_type(&self, index: usize, arg_type: &str) -> u32 {
//        unsafe {
//            let cstr = CString::new(arg_type).expect("must be utf8");
//            cass_error_result_arg_type(self.0,
//                                       index,
//                                       &mut cstr.as_ptr(),
//                                       &mut (cstr.to_bytes().len())) as u32
//        }
//    }
// }
// impl Drop for CassErrorResult {
//    fn drop(&mut self) { unsafe { cass_error_result_free(self.0) } }
// }
//
// impl CassError {
//    pub fn new(err:_CassError) -> Self {
//        CassError(err)
//    }
//    fn result_from<T>(self, t:T) -> Result<T> {
//          match self.0 {
//                CASS_OK => Ok(t),
//                err => Err(Error::from(err.into()))
//            }
//    }

fn pointer_to_string<'a>(c_buf: *const c_char) -> &'a str {
    let buf: &[u8] = unsafe { CStr::from_ptr(c_buf).to_bytes() };
    str::from_utf8(buf).unwrap()
}
//    /// Gets the textual description for this error
//    pub fn desc(&self) -> &str {
//        {
//            CassError::pointer_to_string(unsafe { cass_error_desc(self.0) })
//            //            match *self {
//            //                CassError::Lib(ref err) => CassError::pointer_to_string(cass_error_desc(err.err)),
//            //                CassError::Ssl(ref err) => CassError::pointer_to_string(cass_error_desc(err.0)),
//            //                CassError::Server(ref err) => CassError::pointer_to_string(cass_error_desc(err.0)),
//            //                CassError::Rust(ref err) => {
//            //                    match err {
//            //          &CassRustError::NulInString(_) => "Tried to create a CString with a nul in the middle",
//            //                        /// /FIXME how do i return a slice created from self?
//            //                        &CassRustError::BadAddress(_) => "Tried to parse an invalid ip address",
//            //                    }
//            //                }
//            //            }
//        }
//    }
// }