1use std::ffi::CString;
4use std::mem;
5use std::ptr;
6use libc::{c_char, c_void};
7
8use crate::c;
9use crate::error::{TangoResult, TangoError};
10use crate::types::*;
11
12
13pub struct DatabaseProxy {
15 ptr: *mut c_void,
16}
17
18impl Drop for DatabaseProxy {
19 fn drop(&mut self) {
20 let error_stack = unsafe { c::tango_delete_database_proxy(self.ptr) };
21 if !error_stack.is_null() {
22 drop(TangoError::from_stack(error_stack));
24 }
25 }
26}
27
28impl DatabaseProxy {
29 pub fn new() -> TangoResult<DatabaseProxy> {
34 let mut dev = ptr::null_mut();
35 tango_call!(tango_create_database_proxy,
36 DatabaseProxy { ptr: dev },
37 &mut dev)
38 }
39
40 pub fn get_device_exported(&self, name_filter: &str) -> TangoResult<DbDatum> {
47 let c_filter = CString::new(name_filter).unwrap();
48 let mut db_datum = unsafe { mem::zeroed() };
49 tango_call!(tango_get_device_exported,
50 unsafe { DbDatum::from_c(db_datum, true) },
51 self.ptr, c_filter.as_ptr() as *mut c_char, &mut db_datum)
52 }
53
54 pub fn get_device_exported_for_class(&self, class_name: &str) -> TangoResult<DbDatum> {
60 let c_class = CString::new(class_name).unwrap();
61 let mut db_datum = unsafe { mem::zeroed() };
62 tango_call!(tango_get_device_exported_for_class,
63 unsafe { DbDatum::from_c(db_datum, true) },
64 self.ptr, c_class.as_ptr() as *mut c_char, &mut db_datum)
65 }
66
67 pub fn get_object_list(&self, name_filter: &str) -> TangoResult<DbDatum> {
74 let c_filter = CString::new(name_filter).unwrap();
75 let mut db_datum = unsafe { mem::zeroed() };
76 tango_call!(tango_get_object_list,
77 unsafe { DbDatum::from_c(db_datum, true) },
78 self.ptr, c_filter.as_ptr() as *mut c_char, &mut db_datum)
79 }
80
81 pub fn get_object_property_list(&self, obj_name: &str, name_filter: &str) -> TangoResult<DbDatum> {
88 let c_name = CString::new(obj_name).unwrap();
89 let c_filter = CString::new(name_filter).unwrap();
90 let mut db_datum = unsafe { mem::zeroed() };
91 tango_call!(tango_get_object_property_list,
92 unsafe { DbDatum::from_c(db_datum, true) },
93 self.ptr, c_name.as_ptr() as *mut c_char,
94 c_filter.as_ptr() as *mut c_char, &mut db_datum)
95 }
96
97 pub fn get_property(&self, obj_name: &str, prop_list: Vec<DbDatum>) -> TangoResult<Vec<DbDatum>> {
102 let c_name = CString::new(obj_name).unwrap();
103 let mut db_data = unsafe { mem::zeroed::<c::DbData>() };
104 let mut ptr_vec = Vec::with_capacity(prop_list.len());
105 let mut cstr_vec = Vec::with_capacity(prop_list.len());
106 db_data.length = prop_list.len() as u32;
107 for datum in prop_list {
108 let (datum, cstr) = unsafe { datum.into_c() };
109 ptr_vec.push(datum);
110 cstr_vec.push(cstr);
111 }
112 db_data.sequence = ptr_vec.as_mut_ptr();
113 tango_call!(tango_get_property, (), self.ptr,
114 c_name.as_ptr() as *mut c_char, &mut db_data)?;
115 let mut res = Vec::with_capacity(db_data.length as usize);
116 unsafe {
117 for i in 0..db_data.length {
118 let db_datum = ptr::read(db_data.sequence.offset(i as isize));
119 res.push(DbDatum::from_c(db_datum, false));
120 }
121 c::tango_free_DbData(&mut db_data);
122 }
123 Ok(res)
124 }
125
126 pub fn put_property(&mut self, obj_name: &str, prop_list: Vec<DbDatum>) -> TangoResult<()> {
128 let c_name = CString::new(obj_name).unwrap();
129 let mut db_data = unsafe { mem::zeroed::<c::DbData>() };
130 let mut ptr_vec = Vec::with_capacity(prop_list.len());
131 let mut cstr_vec = Vec::with_capacity(prop_list.len());
132 db_data.length = prop_list.len() as u32;
133 for datum in prop_list {
134 let (datum, cstr) = unsafe { datum.into_c() };
135 ptr_vec.push(datum);
136 cstr_vec.push(cstr);
137 }
138 db_data.sequence = ptr_vec.as_mut_ptr();
139 let res = tango_call!(tango_put_property, (),
140 self.ptr, c_name.as_ptr() as *mut c_char, &mut db_data);
141 unsafe {
142 for ptr in ptr_vec {
143 DbDatum::free_c_data(ptr);
144 }
145 }
146 res
147 }
148
149 pub fn delete_property(&mut self, obj_name: &str, prop_list: &[&str]) -> TangoResult<()> {
151 let c_name = CString::new(obj_name).unwrap();
152 let mut db_data = unsafe { mem::zeroed::<c::DbData>() };
153 let mut ptr_vec = Vec::with_capacity(prop_list.len());
154 let mut cstr_vec = Vec::with_capacity(prop_list.len());
155 db_data.length = prop_list.len() as u32;
156 for prop in prop_list {
157 let datum = DbDatum::name_only(prop);
158 let (datum, cstr) = unsafe { datum.into_c() };
159 ptr_vec.push(datum);
160 cstr_vec.push(cstr);
161 }
162 db_data.sequence = ptr_vec.as_mut_ptr();
163 let res = tango_call!(tango_delete_property, (),
164 self.ptr, c_name.as_ptr() as *mut c_char, &mut db_data);
165 unsafe {
166 for ptr in ptr_vec {
167 DbDatum::free_c_data(ptr);
168 }
169 }
170 res
171 }
172}