#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
use crate::cassandra::cluster::Cluster;
use crate::cassandra::error::*;
use crate::cassandra::future::CassFuture;
use crate::cassandra::metrics::SessionMetrics;
use crate::cassandra::prepared::PreparedStatement;
use crate::cassandra::result::CassResult;
use crate::cassandra::schema::schema_meta::SchemaMeta;
use crate::cassandra::statement::Statement;
use crate::cassandra::util::{Protected, ProtectedInner};
use crate::{cassandra::batch::Batch, BatchType};
use crate::cassandra_sys::cass_session_close;
use crate::cassandra_sys::cass_session_connect;
use crate::cassandra_sys::cass_session_connect_keyspace_n;
use crate::cassandra_sys::cass_session_execute;
use crate::cassandra_sys::cass_session_execute_batch;
use crate::cassandra_sys::cass_session_free;
use crate::cassandra_sys::cass_session_get_metrics;
use crate::cassandra_sys::cass_session_get_schema_meta;
use crate::cassandra_sys::cass_session_new;
use crate::cassandra_sys::cass_session_prepare_n;
use crate::cassandra_sys::CassSession as _Session;
use std::ffi::NulError;
use std::mem;
use std::os::raw::c_char;
use std::sync::Arc;
#[derive(Debug, Eq, PartialEq)]
struct SessionInner<T>(T, *mut _Session);
unsafe impl<T: Send> Send for SessionInner<T> {}
unsafe impl<T: Sync> Sync for SessionInner<T> {}
impl<T> SessionInner<T> {
fn new(bound: T, inner: *mut _Session) -> Arc<Self> {
Arc::new(Self(bound, inner))
}
}
pub trait SessionScope: session_scope::sealed::Sealed + Clone + Send + Sync + 'static {}
pub mod session_scope {
pub use super::SessionScope;
pub(super) mod sealed {
pub trait Sealed {}
}
#[derive(Debug, Clone)]
pub struct Bound {
pub(crate) keyspace: String,
}
impl Bound {
pub(crate) fn new(keyspace: impl Into<String>) -> Self {
Self {
keyspace: keyspace.into(),
}
}
}
#[derive(Debug, Clone)]
pub struct Unbound;
impl sealed::Sealed for Bound {}
impl sealed::Sealed for Unbound {}
impl super::SessionScope for Bound {}
impl super::SessionScope for Unbound {}
}
#[derive(Debug, Clone)]
pub struct Session<T = session_scope::Bound>(Arc<SessionInner<T>>);
impl<T> Eq for Session<T> {}
impl<T> PartialEq for Session<T> {
fn eq(&self, other: &Self) -> bool {
(self.0).1 == (other.0).1
}
}
unsafe impl<T: Send> Send for Session<T> {}
unsafe impl<T: Sync> Sync for Session<T> {}
impl<T> ProtectedInner<*mut _Session> for SessionInner<T> {
fn inner(&self) -> *mut _Session {
self.1
}
}
impl<T> ProtectedInner<*mut _Session> for Session<T> {
fn inner(&self) -> *mut _Session {
self.0.inner()
}
}
impl Protected<*mut _Session> for Session<session_scope::Unbound> {
fn build(inner: *mut _Session) -> Self {
if inner.is_null() {
panic!("Unexpected null pointer")
};
Session(SessionInner::new(session_scope::Unbound, inner))
}
}
impl<T> Drop for SessionInner<T> {
fn drop(&mut self) {
unsafe { cass_session_free(self.1) }
}
}
impl Default for Session<session_scope::Unbound> {
fn default() -> Session<session_scope::Unbound> {
Session::new(session_scope::Unbound)
}
}
impl<S> Session<S>
where
S: SessionScope,
{
pub(crate) fn new(bound: S) -> Self {
unsafe { Session(SessionInner::new(bound, cass_session_new())) }
}
pub fn statement(&self, query: impl AsRef<str>) -> Statement<S> {
let query = query.as_ref();
let param_count = query.matches("?").count();
Statement::new(self.clone(), query, param_count)
}
pub async fn execute(&self, query: impl AsRef<str>) -> Result<CassResult> {
let statement = self.statement(query);
statement.execute().await
}
pub fn batch(&self, batch_type: BatchType) -> Batch<S> {
Batch::new(batch_type, self.clone())
}
pub fn get_schema_meta(&self) -> SchemaMeta {
unsafe { SchemaMeta::build(cass_session_get_schema_meta(self.inner())) }
}
pub fn get_metrics(&self) -> SessionMetrics {
unsafe {
let mut metrics = mem::zeroed();
cass_session_get_metrics(self.inner(), &mut metrics);
SessionMetrics::build(&metrics)
}
}
pub async fn prepare(&self, query: impl AsRef<str>) -> Result<PreparedStatement<S>> {
let query = query.as_ref();
let prepare_future = {
let query_ptr = query.as_ptr() as *const c_char;
CassFuture::build(self.clone(), unsafe {
cass_session_prepare_n(self.inner(), query_ptr, query.len())
})
};
prepare_future.await
}
}
impl Session<session_scope::Bound> {
pub fn keyspace(&self) -> &str {
&(self.0).0.keyspace
}
}