cassandra_cpp/cassandra/
data_type.rs

1use crate::cassandra::error::*;
2use crate::cassandra::user_type::UserType;
3use crate::cassandra::util::{Protected, ProtectedInner};
4use crate::cassandra::value::ValueType;
5
6use crate::cassandra_sys::cass_data_sub_type_count;
7use crate::cassandra_sys::cass_data_type_add_sub_type;
8use crate::cassandra_sys::cass_data_type_add_sub_type_by_name_n;
9use crate::cassandra_sys::cass_data_type_add_sub_value_type;
10use crate::cassandra_sys::cass_data_type_add_sub_value_type_by_name_n;
11use crate::cassandra_sys::cass_data_type_class_name;
12use crate::cassandra_sys::cass_data_type_free;
13use crate::cassandra_sys::cass_data_type_keyspace;
14use crate::cassandra_sys::cass_data_type_new;
15use crate::cassandra_sys::cass_data_type_new_from_existing;
16use crate::cassandra_sys::cass_data_type_new_tuple;
17use crate::cassandra_sys::cass_data_type_new_udt;
18use crate::cassandra_sys::cass_data_type_set_class_name_n;
19use crate::cassandra_sys::cass_data_type_set_keyspace_n;
20use crate::cassandra_sys::cass_data_type_set_type_name_n;
21use crate::cassandra_sys::cass_data_type_sub_data_type;
22use crate::cassandra_sys::cass_data_type_sub_data_type_by_name_n;
23use crate::cassandra_sys::cass_data_type_sub_type_name;
24use crate::cassandra_sys::cass_data_type_type;
25use crate::cassandra_sys::cass_data_type_type_name;
26use crate::cassandra_sys::cass_user_type_new_from_data_type;
27use crate::cassandra_sys::CassDataType as _CassDataType;
28
29use std::ffi::CString;
30use std::marker::PhantomData;
31use std::os::raw::c_char;
32
33/// Any Cassandra datatype. This is an owned type.
34#[derive(Debug)]
35pub struct DataType(*mut _CassDataType);
36
37/// Any Cassandra datatype. This is a reference type.
38//
39// Borrowed from whatever descriptor contains the type, e.g., a `SchemaMeta`.
40#[derive(Debug)]
41pub struct ConstDataType<'a>(*const _CassDataType, PhantomData<&'a _CassDataType>);
42
43// The underlying C types have no thread-local state, and forbids only concurrent
44// mutation/free: https://datastax.github.io/cpp-driver/topics/#thread-safety
45unsafe impl Send for DataType {}
46unsafe impl Sync for DataType {}
47unsafe impl Send for ConstDataType<'_> {}
48unsafe impl Sync for ConstDataType<'_> {}
49
50impl ProtectedInner<*mut _CassDataType> for DataType {
51    fn inner(&self) -> *mut _CassDataType {
52        self.0
53    }
54}
55
56impl Protected<*mut _CassDataType> for DataType {
57    fn build(inner: *mut _CassDataType) -> Self {
58        if inner.is_null() {
59            panic!("Unexpected null pointer")
60        };
61        DataType(inner)
62    }
63}
64
65impl ProtectedInner<*const _CassDataType> for ConstDataType<'_> {
66    fn inner(&self) -> *const _CassDataType {
67        self.0
68    }
69}
70
71impl Protected<*const _CassDataType> for ConstDataType<'_> {
72    fn build(inner: *const _CassDataType) -> Self {
73        if inner.is_null() {
74            panic!("Unexpected null pointer")
75        };
76        ConstDataType(inner, PhantomData)
77    }
78}
79
80impl Drop for DataType {
81    /// Frees a data type instance.
82    fn drop(&mut self) {
83        unsafe { cass_data_type_free(self.0) }
84    }
85}
86
87impl ConstDataType<'_> {
88    /// Creates a new user defined type from existing data type.
89    pub fn new_user_type(&self) -> UserType {
90        unsafe { UserType::build(cass_user_type_new_from_data_type(self.0)) }
91    }
92}
93
94impl DataType {
95    /// Creates a new data type with value type.
96    pub fn new(value_type: ValueType) -> Self {
97        unsafe { DataType(cass_data_type_new(value_type.inner())) }
98    }
99
100    /// Creates a new data type from an existing data type.
101    // TODO: can return NULL
102    pub fn new_user_type(&self) -> UserType {
103        unsafe { UserType::build(cass_user_type_new_from_data_type(self.0)) }
104    }
105
106    /// Creates a new data type from an existing data type.
107    pub fn new_from_existing(&self) -> Self {
108        unsafe { DataType(cass_data_type_new_from_existing(self.0)) }
109    }
110
111    /// Creates a new tuple data type.
112    pub fn new_tuple(item_count: usize) -> Self {
113        unsafe { DataType(cass_data_type_new_tuple(item_count)) }
114    }
115
116    /// Creates a new UDT (user defined type) data type.
117    pub fn new_udt(field_count: usize) -> DataType {
118        unsafe { DataType(cass_data_type_new_udt(field_count)) }
119    }
120
121    /// Gets the value type of the specified data type.
122    pub fn get_type(data_type: DataType) -> ValueType {
123        unsafe { ValueType::build(cass_data_type_type(data_type.0)) }
124    }
125
126    /// Gets the type name of a UDT data type.
127    pub fn type_name<S>(data_type: DataType, type_name: S) -> Result<()>
128    where
129        S: Into<String>,
130    {
131        unsafe {
132            let type_name2 = CString::new(type_name.into())?;
133            let err = cass_data_type_type_name(
134                data_type.0,
135                &mut type_name2.as_ptr(),
136                &mut (type_name2.as_bytes().len()),
137            );
138            err.to_result(())
139        }
140    }
141
142    /// Sets the type name of a UDT data type.
143    ///
144    /// <b>Note:</b> Only valid for UDT data types.
145    pub fn set_type_name<S>(data_type: DataType, type_name: S) -> Result<()>
146    where
147        S: Into<String>,
148    {
149        unsafe {
150            let type_name_str = type_name.into();
151            let type_name_ptr = type_name_str.as_ptr() as *const c_char;
152            cass_data_type_set_type_name_n(data_type.0, type_name_ptr, type_name_str.len())
153                .to_result(())
154        }
155    }
156
157    /// Gets the type name of a UDT data type.
158    ///
159    /// <b>Note:</b> Only valid for UDT data types.
160    pub fn keyspace<S>(data_type: DataType, keyspace: S) -> Result<()>
161    where
162        S: Into<String>,
163    {
164        unsafe {
165            let keyspace2 = CString::new(keyspace.into())?;
166            cass_data_type_keyspace(
167                data_type.0,
168                &mut (keyspace2.as_ptr()),
169                &mut (keyspace2.as_bytes().len()),
170            )
171            .to_result(())
172        }
173    }
174
175    /// Sets the keyspace of a UDT data type.
176    ///
177    /// <b>Note:</b> Only valid for UDT data types.
178    pub fn set_keyspace<S>(data_type: DataType, keyspace: S) -> Result<()>
179    where
180        S: Into<String>,
181    {
182        unsafe {
183            let keyspace_str = keyspace.into();
184            let keyspace_ptr = keyspace_str.as_ptr() as *const c_char;
185            cass_data_type_set_keyspace_n(data_type.0, keyspace_ptr, keyspace_str.len())
186                .to_result(())
187        }
188    }
189
190    /// Gets the class name of a custom data type.
191    ///
192    /// <b>Note:</b> Only valid for custom data types.
193    pub fn class_name<S>(data_type: DataType, class_name: S) -> Result<()>
194    where
195        S: Into<String>,
196    {
197        unsafe {
198            let class_name2 = CString::new(class_name.into())?;
199            cass_data_type_class_name(
200                data_type.0,
201                &mut class_name2.as_ptr(),
202                &mut (class_name2.as_bytes().len()),
203            )
204            .to_result(())
205        }
206    }
207
208    /// Sets the class name of a custom data type.
209    ///
210    /// <b>Note:</b> Only valid for custom data types.
211    pub fn set_class_name<S>(&self, class_name: S) -> Result<()>
212    where
213        S: Into<String>,
214    {
215        unsafe {
216            let class_name_str = class_name.into();
217            let class_name_ptr = class_name_str.as_ptr() as *const c_char;
218            cass_data_type_set_class_name_n(self.0, class_name_ptr, class_name_str.len())
219                .to_result(())
220        }
221    }
222
223    /// Gets the sub-data type count of a UDT (user defined type), tuple
224    /// or collection.
225    ///
226    /// <b>Note:</b> Only valid for UDT, tuple and collection data types.
227    pub fn sub_type_count<S>(&self) -> usize {
228        unsafe { cass_data_sub_type_count(self.0) }
229    }
230
231    /// Gets the sub-data type of a UDT (user defined type), tuple or collection at
232    /// the specified index.
233    ///
234    /// <b>Note:</b> Only valid for UDT, tuple and collection data types.
235    pub fn sub_data_type(&self, index: usize) -> ConstDataType {
236        // TODO: can return NULL
237        unsafe { ConstDataType::build(cass_data_type_sub_data_type(self.0, index)) }
238    }
239
240    /// Gets the sub-data type of a UDT (user defined type) at the specified index.
241    ///
242    /// <b>Note:</b> Only valid for UDT data types.
243    pub fn sub_data_type_by_name<S>(&self, name: S) -> ConstDataType
244    where
245        S: Into<String>,
246    {
247        unsafe {
248            let name_str = name.into();
249            let name_ptr = name_str.as_ptr() as *const c_char;
250            // TODO: can return NULL
251            ConstDataType::build(cass_data_type_sub_data_type_by_name_n(
252                self.0,
253                name_ptr,
254                name_str.len(),
255            ))
256        }
257    }
258
259    /// Gets the sub-type name of a UDT (user defined type) at the specified index.
260    ///
261    /// <b>Note:</b> Only valid for UDT data types.
262    pub fn sub_type_name<S>(&self, index: usize, name: S) -> Result<()>
263    where
264        S: Into<String>,
265    {
266        unsafe {
267            let name2 = CString::new(name.into())?;
268            cass_data_type_sub_type_name(
269                self.0,
270                index,
271                &mut name2.as_ptr(),
272                &mut (name2.as_bytes().len()),
273            )
274            .to_result(())
275        }
276    }
277
278    /// Adds a sub-data type to a tuple or collection.
279    ///
280    /// <b>Note:</b> Only valid for tuple and collection data types.
281    pub fn add_sub_type(&self, sub_data_type: DataType) -> Result<()> {
282        unsafe { cass_data_type_add_sub_type(self.0, sub_data_type.0).to_result(()) }
283    }
284
285    /// Gets the sub-data type of a UDT (user defined type) at the specified index.
286    ///
287    /// <b>Note:</b> Only valid for UDT data types.
288    pub fn add_sub_type_by_name<S>(&mut self, name: S, sub_data_type: DataType) -> Result<()>
289    where
290        S: Into<String>,
291    {
292        unsafe {
293            let name_str = name.into();
294            let name_ptr = name_str.as_ptr() as *const c_char;
295            cass_data_type_add_sub_type_by_name_n(self.0, name_ptr, name_str.len(), sub_data_type.0)
296                .to_result(())
297        }
298    }
299
300    /// Adds a sub-data type to a tuple or collection using a value type.
301    ///
302    /// <b>Note:</b> Only valid for tuple and collection data types.
303    pub fn add_sub_value_type<S>(&self, sub_value_type: ValueType) -> Result<()>
304    where
305        S: Into<String>,
306    {
307        unsafe { cass_data_type_add_sub_value_type(self.0, sub_value_type.inner()).to_result(()) }
308    }
309
310    /// Adds a sub-data type to a tuple or collection using a value type.
311    ///
312    /// <b>Note:</b> Only valid for tuple and collection data types.
313    pub fn add_sub_value_type_by_name<S>(&self, name: S, typ: ValueType) -> Result<()>
314    where
315        S: Into<String>,
316    {
317        unsafe {
318            let name_str = name.into();
319            let name_ptr = name_str.as_ptr() as *const c_char;
320            cass_data_type_add_sub_value_type_by_name_n(
321                self.0,
322                name_ptr,
323                name_str.len(),
324                typ.inner(),
325            )
326            .to_result(())
327        }
328    }
329
330    //    pub fn set_type_name_n<S>(data_type: DataType, type_name: S) -> Result<(), CassError>
331    //        where S: Into<String>
332    //    {
333    //        unsafe {
334    //            let type_name = CString::new(type_name.into()).unwrap();
335    //            CassError::build(cass_data_type_set_type_name_n(data_type.0,
336    //                                                            type_name.as_ptr(),
337    //                                                            type_name.as_bytes().len() as u64))
338    //                .wrap(())
339    //        }
340    //    }
341
342    //    pub fn set_class_name_n<S>(data_type: DataType, class_name: S) -> Result<(), CassError>
343    //        where S: Into<String>
344    //    {
345    //        unsafe {
346    //            let class_name = CString::new(class_name.into()).unwrap();
347    //            CassError::build(cass_data_type_set_class_name_n(data_type.0,
348    //                                                             class_name.as_ptr(),
349    //                                                             class_name.as_bytes().len() as u64))
350    //                .wrap(())
351    //        }
352    //    }
353
354    //    pub fn sub_data_type_by_name_n<S>(data_type: DataType, name: S) -> ConstDataType
355    //        where S: Into<String>
356    //    {
357    //        unsafe {
358    //            let name = CString::new(name.into()).unwrap();
359    //            // TODO: can return NULL
360    //            ConstDataType::build(cass_data_type_sub_data_type_by_name_n(data_type.0,
361    //                                                                 name.as_ptr(),
362    //                                                                 name.as_bytes().len() as u64))
363    //        }
364    //    }
365}