1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::cassandra::error::*;
use crate::cassandra::util::{Protected, ProtectedInner};

use crate::cassandra_sys::cass_custom_payload_free;
use crate::cassandra_sys::cass_custom_payload_new;

use crate::cassandra_sys::cass_custom_payload_set_n;
use crate::cassandra_sys::CassCustomPayload as _CassCustomPayload;
use std::collections::HashMap;
use std::os::raw::c_char;

pub type CustomPayloadResponse = HashMap<String, Vec<u8>>;

/// Custom payloads not fully supported yet
#[derive(Debug)]
pub struct CustomPayload(*mut _CassCustomPayload);

// The underlying C type has no thread-local state, and forbids only concurrent
// mutation/free: https://datastax.github.io/cpp-driver/topics/#thread-safety
unsafe impl Send for CustomPayload {}
unsafe impl Sync for CustomPayload {}

impl ProtectedInner<*mut _CassCustomPayload> for CustomPayload {
    #[inline(always)]
    fn inner(&self) -> *mut _CassCustomPayload {
        self.0
    }
}

impl Protected<*mut _CassCustomPayload> for CustomPayload {
    fn build(inner: *mut _CassCustomPayload) -> Self {
        if inner.is_null() {
            panic!("Unexpected null pointer")
        };
        CustomPayload(inner)
    }
}

impl Default for CustomPayload {
    /// creates a new custom payload
    fn default() -> Self {
        unsafe { CustomPayload(cass_custom_payload_new()) }
    }
}

impl CustomPayload {
    /// Sets an item to the custom payload.
    pub fn set(&self, name: String, value: &[u8]) -> Result<()> {
        unsafe {
            let name_ptr = name.as_ptr() as *const c_char;
            cass_custom_payload_set_n(self.0, name_ptr, name.len(), value.as_ptr(), value.len());
            Ok(())
        }
    }
}

impl Drop for CustomPayload {
    fn drop(&mut self) {
        unsafe { cass_custom_payload_free(self.0) }
    }
}