1#![allow(clippy::type_complexity)]
10
11use crate::sys::cmap as ffi;
13
14use num_enum::TryFromPrimitive;
15use std::any::type_name;
16use std::collections::HashMap;
17use std::convert::TryFrom;
18use std::ffi::CString;
19use std::fmt;
20use std::os::raw::{c_char, c_int, c_void};
21use std::ptr::copy_nonoverlapping;
22use std::sync::Mutex;
23
24use crate::string_from_bytes;
25use crate::{CsError, DispatchFlags, Result};
26
27pub enum Map {
30 Icmap,
31 Stats,
32}
33
34bitflags! {
35pub struct TrackType: i32
38 {
39 const DELETE = 1;
40 const MODIFY = 2;
41 const ADD = 4;
42 const PREFIX = 8;
43 }
44}
45
46impl fmt::Display for TrackType {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 if self.contains(TrackType::DELETE) {
49 write!(f, "DELETE ")?
50 }
51 if self.contains(TrackType::MODIFY) {
52 write!(f, "MODIFY ")?
53 }
54 if self.contains(TrackType::ADD) {
55 write!(f, "ADD ")?
56 }
57 if self.contains(TrackType::PREFIX) {
58 write!(f, "PREFIX ")
59 } else {
60 Ok(())
61 }
62 }
63}
64
65pub struct Handle {
67 cmap_handle: u64,
68 clone: bool,
69}
70
71impl Clone for Handle {
72 fn clone(&self) -> Handle {
73 Handle {
74 cmap_handle: self.cmap_handle,
75 clone: true,
76 }
77 }
78}
79
80impl Drop for Handle {
81 fn drop(self: &mut Handle) {
82 if !self.clone {
83 let _e = finalize(self);
84 }
85 }
86}
87impl PartialEq for Handle {
89 fn eq(&self, other: &Handle) -> bool {
90 self.cmap_handle == other.cmap_handle
91 }
92}
93
94#[derive(Copy, Clone)]
95pub struct TrackHandle {
98 track_handle: u64,
99 notify_callback: NotifyCallback,
100}
101
102lazy_static! {
104 static ref TRACKHANDLE_HASH: Mutex<HashMap<u64, TrackHandle>> = Mutex::new(HashMap::new());
105 static ref HANDLE_HASH: Mutex<HashMap<u64, Handle>> = Mutex::new(HashMap::new());
106}
107
108pub fn initialize(map: Map) -> Result<Handle> {
112 let mut handle: ffi::cmap_handle_t = 0;
113 let c_map = match map {
114 Map::Icmap => ffi::CMAP_MAP_ICMAP,
115 Map::Stats => ffi::CMAP_MAP_STATS,
116 };
117
118 unsafe {
119 let res = ffi::cmap_initialize_map(&mut handle, c_map);
120 if res == ffi::CS_OK {
121 let rhandle = Handle {
122 cmap_handle: handle,
123 clone: false,
124 };
125 HANDLE_HASH.lock().unwrap().insert(handle, rhandle.clone());
126 Ok(rhandle)
127 } else {
128 Err(CsError::from_c(res))
129 }
130 }
131}
132
133pub fn finalize(handle: &Handle) -> Result<()> {
136 let res = unsafe { ffi::cmap_finalize(handle.cmap_handle) };
137 if res == ffi::CS_OK {
138 HANDLE_HASH.lock().unwrap().remove(&handle.cmap_handle);
139 Ok(())
140 } else {
141 Err(CsError::from_c(res))
142 }
143}
144
145pub fn fd_get(handle: &Handle) -> Result<i32> {
149 let c_fd: *mut c_int = &mut 0 as *mut _ as *mut c_int;
150 let res = unsafe { ffi::cmap_fd_get(handle.cmap_handle, c_fd) };
151 if res == ffi::CS_OK {
152 Ok(unsafe { *c_fd })
153 } else {
154 Err(CsError::from_c(res))
155 }
156}
157
158pub fn dispatch(handle: &Handle, flags: DispatchFlags) -> Result<()> {
162 let res = unsafe { ffi::cmap_dispatch(handle.cmap_handle, flags as u32) };
163 if res == ffi::CS_OK {
164 Ok(())
165 } else {
166 Err(CsError::from_c(res))
167 }
168}
169
170pub fn context_get(handle: &Handle) -> Result<u64> {
174 let (res, context) = unsafe {
175 let mut context: u64 = 0;
176 let c_context: *mut c_void = &mut context as *mut _ as *mut c_void;
177 let r = ffi::cmap_context_get(handle.cmap_handle, c_context as *mut *const c_void);
178 (r, context)
179 };
180 if res == ffi::CS_OK {
181 Ok(context)
182 } else {
183 Err(CsError::from_c(res))
184 }
185}
186
187pub fn context_set(handle: &Handle, context: u64) -> Result<()> {
192 let res = unsafe {
193 let c_context = context as *mut c_void;
194 ffi::cmap_context_set(handle.cmap_handle, c_context)
195 };
196 if res == ffi::CS_OK {
197 Ok(())
198 } else {
199 Err(CsError::from_c(res))
200 }
201}
202
203#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
206#[repr(u32)]
207pub enum DataType {
208 Int8 = ffi::CMAP_VALUETYPE_INT8,
209 UInt8 = ffi::CMAP_VALUETYPE_UINT8,
210 Int16 = ffi::CMAP_VALUETYPE_INT16,
211 UInt16 = ffi::CMAP_VALUETYPE_UINT16,
212 Int32 = ffi::CMAP_VALUETYPE_INT32,
213 UInt32 = ffi::CMAP_VALUETYPE_UINT32,
214 Int64 = ffi::CMAP_VALUETYPE_INT64,
215 UInt64 = ffi::CMAP_VALUETYPE_UINT64,
216 Float = ffi::CMAP_VALUETYPE_FLOAT,
217 Double = ffi::CMAP_VALUETYPE_DOUBLE,
218 String = ffi::CMAP_VALUETYPE_STRING,
219 Binary = ffi::CMAP_VALUETYPE_BINARY,
220 Unknown = 999,
221}
222
223fn cmap_to_enum(cmap_type: u32) -> DataType {
224 match DataType::try_from(cmap_type) {
225 Ok(e) => e,
226 Err(_) => DataType::Unknown,
227 }
228}
229
230pub enum Data {
233 Int8(i8),
234 UInt8(u8),
235 Int16(i16),
236 UInt16(u16),
237 Int32(i32),
238 UInt32(u32),
239 Int64(i64),
240 UInt64(u64),
241 Float(f32),
242 Double(f64),
243 String(String),
244 Binary(Vec<u8>),
245 Unknown,
246}
247
248impl fmt::Display for DataType {
249 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250 match self {
251 DataType::Int8 => write!(f, "Int8"),
252 DataType::UInt8 => write!(f, "UInt8"),
253 DataType::Int16 => write!(f, "Int16"),
254 DataType::UInt16 => write!(f, "UInt16"),
255 DataType::Int32 => write!(f, "Int32"),
256 DataType::UInt32 => write!(f, "UInt32"),
257 DataType::Int64 => write!(f, "Int64"),
258 DataType::UInt64 => write!(f, "UInt64"),
259 DataType::Float => write!(f, "Float"),
260 DataType::Double => write!(f, "Double"),
261 DataType::String => write!(f, "String"),
262 DataType::Binary => write!(f, "Binary"),
263 DataType::Unknown => write!(f, "Unknown"),
264 }
265 }
266}
267
268impl fmt::Display for Data {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 match self {
271 Data::Int8(v) => write!(f, "{v} (Int8)"),
272 Data::UInt8(v) => write!(f, "{v} (UInt8)"),
273 Data::Int16(v) => write!(f, "{v} (Int16)"),
274 Data::UInt16(v) => write!(f, "{v} (UInt16)"),
275 Data::Int32(v) => write!(f, "{v} (Int32)"),
276 Data::UInt32(v) => write!(f, "{v} (UInt32)"),
277 Data::Int64(v) => write!(f, "{v} (Int64)"),
278 Data::UInt64(v) => write!(f, "{v} (UInt64)"),
279 Data::Float(v) => write!(f, "{v} (Float)"),
280 Data::Double(v) => write!(f, "{v} (Double)"),
281 Data::String(v) => write!(f, "{v} (String)"),
282 Data::Binary(v) => write!(f, "{v:?} (Binary)"),
283 Data::Unknown => write!(f, "Unknown)"),
284 }
285 }
286}
287
288const CMAP_KEYNAME_MAXLENGTH: usize = 255;
289fn string_to_cstring_validated(key: &str, maxlen: usize) -> Result<CString> {
290 if maxlen > 0 && key.chars().count() >= maxlen {
291 return Err(CsError::CsErrInvalidParam);
292 }
293
294 match CString::new(key) {
295 Ok(n) => Ok(n),
296 Err(_) => Err(CsError::CsErrLibrary),
297 }
298}
299
300fn set_value(
301 handle: &Handle,
302 key_name: &str,
303 datatype: DataType,
304 value: *mut c_void,
305 length: usize,
306) -> Result<()> {
307 let csname = string_to_cstring_validated(key_name, CMAP_KEYNAME_MAXLENGTH)?;
308 let res = unsafe {
309 ffi::cmap_set(
310 handle.cmap_handle,
311 csname.as_ptr(),
312 value,
313 length,
314 datatype as u32,
315 )
316 };
317 if res == ffi::CS_OK {
318 Ok(())
319 } else {
320 Err(CsError::from_c(res))
321 }
322}
323
324fn generic_to_cmap<T>(_value: T) -> (DataType, usize) {
326 match type_name::<T>() {
327 "u8" => (DataType::UInt8, 1),
328 "i8" => (DataType::Int8, 1),
329 "u16" => (DataType::UInt16, 2),
330 "i16" => (DataType::Int16, 2),
331 "u32" => (DataType::UInt32, 4),
332 "i32" => (DataType::Int32, 4),
333 "u64" => (DataType::UInt64, 4),
334 "f32" => (DataType::Float, 4),
335 "f64" => (DataType::Double, 8),
336 "&str" => (DataType::String, 0),
337 _ => (DataType::Unknown, 0),
339 }
340}
341
342fn is_numeric_type(dtype: DataType) -> bool {
343 matches!(
344 dtype,
345 DataType::UInt8
346 | DataType::Int8
347 | DataType::UInt16
348 | DataType::Int16
349 | DataType::UInt32
350 | DataType::Int32
351 | DataType::UInt64
352 | DataType::Int64
353 | DataType::Float
354 | DataType::Double
355 )
356}
357
358pub fn set_number<T: Copy>(handle: &Handle, key_name: &str, value: T) -> Result<()> {
361 let (c_type, c_size) = generic_to_cmap(value);
362
363 if is_numeric_type(c_type) {
364 let mut tmp = value;
365 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
366 set_value(handle, key_name, c_type, c_value as *mut c_void, c_size)
367 } else {
368 Err(CsError::CsErrNotSupported)
369 }
370}
371
372pub fn set_u8(handle: &Handle, key_name: &str, value: u8) -> Result<()> {
373 let mut tmp = value;
374 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
375 set_value(handle, key_name, DataType::UInt8, c_value as *mut c_void, 1)
376}
377
378pub fn set_i8(handle: &Handle, key_name: &str, value: i8) -> Result<()> {
380 let mut tmp = value;
381 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
382 set_value(handle, key_name, DataType::Int8, c_value as *mut c_void, 1)
383}
384
385pub fn set_u16(handle: &Handle, key_name: &str, value: u16) -> Result<()> {
387 let mut tmp = value;
388 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
389 set_value(
390 handle,
391 key_name,
392 DataType::UInt16,
393 c_value as *mut c_void,
394 2,
395 )
396}
397
398pub fn set_i16(handle: &Handle, key_name: &str, value: i16) -> Result<()> {
400 let mut tmp = value;
401 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
402 set_value(handle, key_name, DataType::Int16, c_value as *mut c_void, 2)
403}
404
405pub fn set_u32(handle: &Handle, key_name: &str, value: u32) -> Result<()> {
407 let mut tmp = value;
408 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
409 set_value(handle, key_name, DataType::UInt32, c_value, 4)
410}
411
412pub fn set_i132(handle: &Handle, key_name: &str, value: i32) -> Result<()> {
414 let mut tmp = value;
415 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
416 set_value(handle, key_name, DataType::Int32, c_value as *mut c_void, 4)
417}
418
419pub fn set_u64(handle: &Handle, key_name: &str, value: u64) -> Result<()> {
421 let mut tmp = value;
422 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
423 set_value(
424 handle,
425 key_name,
426 DataType::UInt64,
427 c_value as *mut c_void,
428 8,
429 )
430}
431
432pub fn set_i164(handle: &Handle, key_name: &str, value: i64) -> Result<()> {
434 let mut tmp = value;
435 let c_value: *mut c_void = &mut tmp as *mut _ as *mut c_void;
436 set_value(handle, key_name, DataType::Int64, c_value as *mut c_void, 8)
437}
438
439pub fn set_string(handle: &Handle, key_name: &str, value: &str) -> Result<()> {
441 let v_string = string_to_cstring_validated(value, 0)?;
442 set_value(
443 handle,
444 key_name,
445 DataType::String,
446 v_string.as_ptr() as *mut c_void,
447 value.chars().count(),
448 )
449}
450
451pub fn set_binary(handle: &Handle, key_name: &str, value: &[u8]) -> Result<()> {
453 set_value(
454 handle,
455 key_name,
456 DataType::Binary,
457 value.as_ptr() as *mut c_void,
458 value.len(),
459 )
460}
461
462pub fn set(handle: &Handle, key_name: &str, data: &Data) -> Result<()> {
464 let (datatype, datalen, c_value) = match data {
465 Data::Int8(v) => {
466 let mut tmp = *v;
467 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
468 (DataType::Int8, 1, cv)
469 }
470 Data::UInt8(v) => {
471 let mut tmp = *v;
472 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
473 (DataType::UInt8, 1, cv)
474 }
475 Data::Int16(v) => {
476 let mut tmp = *v;
477 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
478 (DataType::Int16, 2, cv)
479 }
480 Data::UInt16(v) => {
481 let mut tmp = *v;
482 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
483 (DataType::UInt8, 2, cv)
484 }
485 Data::Int32(v) => {
486 let mut tmp = *v;
487 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
488 (DataType::Int32, 4, cv)
489 }
490 Data::UInt32(v) => {
491 let mut tmp = *v;
492 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
493 (DataType::UInt32, 4, cv)
494 }
495 Data::Int64(v) => {
496 let mut tmp = *v;
497 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
498 (DataType::Int64, 8, cv)
499 }
500 Data::UInt64(v) => {
501 let mut tmp = *v;
502 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
503 (DataType::UInt64, 8, cv)
504 }
505 Data::Float(v) => {
506 let mut tmp = *v;
507 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
508 (DataType::Float, 4, cv)
509 }
510 Data::Double(v) => {
511 let mut tmp = *v;
512 let cv: *mut c_void = &mut tmp as *mut _ as *mut c_void;
513 (DataType::Double, 8, cv)
514 }
515 Data::String(v) => {
516 let cv = string_to_cstring_validated(v, 0)?;
517 return set_value(
519 handle,
520 key_name,
521 DataType::String,
522 cv.as_ptr() as *mut c_void,
523 v.chars().count(),
524 );
525 }
526 Data::Binary(v) => {
527 return set_value(
529 handle,
530 key_name,
531 DataType::Binary,
532 v.as_ptr() as *mut c_void,
533 v.len(),
534 );
535 }
536 Data::Unknown => return Err(CsError::CsErrInvalidParam),
537 };
538
539 set_value(handle, key_name, datatype, c_value, datalen)
540}
541
542fn c_to_data(value_size: usize, c_key_type: u32, c_value: *const u8) -> Result<Data> {
546 unsafe {
547 match cmap_to_enum(c_key_type) {
548 DataType::UInt8 => {
549 let mut ints = [0u8; 1];
550 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr(), value_size);
551 Ok(Data::UInt8(ints[0]))
552 }
553 DataType::Int8 => {
554 let mut ints = [0i8; 1];
555 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
556 Ok(Data::Int8(ints[0]))
557 }
558 DataType::UInt16 => {
559 let mut ints = [0u16; 1];
560 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
561 Ok(Data::UInt16(ints[0]))
562 }
563 DataType::Int16 => {
564 let mut ints = [0i16; 1];
565 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
566 Ok(Data::Int16(ints[0]))
567 }
568 DataType::UInt32 => {
569 let mut ints = [0u32; 1];
570 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
571 Ok(Data::UInt32(ints[0]))
572 }
573 DataType::Int32 => {
574 let mut ints = [0i32; 1];
575 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
576 Ok(Data::Int32(ints[0]))
577 }
578 DataType::UInt64 => {
579 let mut ints = [0u64; 1];
580 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
581 Ok(Data::UInt64(ints[0]))
582 }
583 DataType::Int64 => {
584 let mut ints = [0i64; 1];
585 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
586 Ok(Data::Int64(ints[0]))
587 }
588 DataType::Float => {
589 let mut ints = [0f32; 1];
590 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
591 Ok(Data::Float(ints[0]))
592 }
593 DataType::Double => {
594 let mut ints = [0f64; 1];
595 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr() as *mut u8, value_size);
596 Ok(Data::Double(ints[0]))
597 }
598 DataType::String => {
599 let mut ints = vec![0u8; value_size];
600 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr(), value_size);
601 let cs = match CString::new(&ints[0..value_size - 1_usize]) {
603 Ok(c1) => c1,
604 Err(_) => return Err(CsError::CsErrLibrary),
605 };
606 match cs.into_string() {
607 Ok(s) => Ok(Data::String(s)),
608 Err(_) => Err(CsError::CsErrLibrary),
609 }
610 }
611 DataType::Binary => {
612 let mut ints = vec![0u8; value_size];
613 copy_nonoverlapping(c_value as *mut u8, ints.as_mut_ptr(), value_size);
614 Ok(Data::Binary(ints))
615 }
616 DataType::Unknown => Ok(Data::Unknown),
617 }
618 }
619}
620
621const INITIAL_SIZE: usize = 256;
622
623pub fn get(handle: &Handle, key_name: &str) -> Result<Data> {
625 let csname = string_to_cstring_validated(key_name, CMAP_KEYNAME_MAXLENGTH)?;
626 let mut value_size: usize = 16;
627 let mut c_key_type: u32 = 0;
628
629 let mut c_value = vec![0u8; INITIAL_SIZE];
631
632 unsafe {
633 let res = ffi::cmap_get(
634 handle.cmap_handle,
635 csname.as_ptr(),
636 c_value.as_mut_ptr() as *mut c_void,
637 &mut value_size,
638 &mut c_key_type,
639 );
640 if res == ffi::CS_OK {
641 if value_size > INITIAL_SIZE {
642 c_value.resize(value_size, 0u8);
644 let res2 = ffi::cmap_get(
645 handle.cmap_handle,
646 csname.as_ptr(),
647 c_value.as_mut_ptr() as *mut c_void,
648 &mut value_size,
649 &mut c_key_type,
650 );
651 if res2 != ffi::CS_OK {
652 return Err(CsError::from_c(res2));
653 }
654 }
655
656 c_to_data(value_size, c_key_type, c_value.as_ptr())
658 } else {
659 Err(CsError::from_c(res))
660 }
661 }
662}
663
664pub fn inc(handle: &Handle, key_name: &str) -> Result<()> {
666 let csname = string_to_cstring_validated(key_name, CMAP_KEYNAME_MAXLENGTH)?;
667 let res = unsafe { ffi::cmap_inc(handle.cmap_handle, csname.as_ptr()) };
668 if res == ffi::CS_OK {
669 Ok(())
670 } else {
671 Err(CsError::from_c(res))
672 }
673}
674
675pub fn dec(handle: &Handle, key_name: &str) -> Result<()> {
677 let csname = string_to_cstring_validated(key_name, CMAP_KEYNAME_MAXLENGTH)?;
678 let res = unsafe { ffi::cmap_dec(handle.cmap_handle, csname.as_ptr()) };
679 if res == ffi::CS_OK {
680 Ok(())
681 } else {
682 Err(CsError::from_c(res))
683 }
684}
685
686extern "C" fn rust_notify_fn(
688 cmap_handle: ffi::cmap_handle_t,
689 cmap_track_handle: ffi::cmap_track_handle_t,
690 event: i32,
691 key_name: *const ::std::os::raw::c_char,
692 new_value: ffi::cmap_notify_value,
693 old_value: ffi::cmap_notify_value,
694 user_data: *mut ::std::os::raw::c_void,
695) {
696 if let Some(r_cmap_handle) = HANDLE_HASH.lock().unwrap().get(&cmap_handle) {
698 if let Some(h) = TRACKHANDLE_HASH.lock().unwrap().get(&cmap_track_handle) {
699 let r_keyname = match string_from_bytes(key_name, CMAP_KEYNAME_MAXLENGTH) {
700 Ok(s) => s,
701 Err(_) => return,
702 };
703
704 let r_old = match c_to_data(old_value.len, old_value.type_, old_value.data as *const u8)
705 {
706 Ok(v) => v,
707 Err(_) => return,
708 };
709 let r_new = match c_to_data(new_value.len, new_value.type_, new_value.data as *const u8)
710 {
711 Ok(v) => v,
712 Err(_) => return,
713 };
714
715 if let Some(cb) = h.notify_callback.notify_fn {
716 (cb)(
717 r_cmap_handle,
718 h,
719 TrackType::from_bits(event).unwrap_or(TrackType::empty()),
720 &r_keyname,
721 &r_old,
722 &r_new,
723 user_data as u64,
724 );
725 }
726 }
727 }
728}
729
730#[derive(Copy, Clone)]
732pub struct NotifyCallback {
733 pub notify_fn: Option<
734 fn(
735 handle: &Handle,
736 track_handle: &TrackHandle,
737 event: TrackType,
738 key_name: &str,
739 new_value: &Data,
740 old_value: &Data,
741 user_data: u64,
742 ),
743 >,
744}
745
746pub fn track_add(
748 handle: &Handle,
749 key_name: &str,
750 track_type: TrackType,
751 notify_callback: &NotifyCallback,
752 user_data: u64,
753) -> Result<TrackHandle> {
754 let c_name = string_to_cstring_validated(key_name, CMAP_KEYNAME_MAXLENGTH)?;
755 let mut c_trackhandle = 0u64;
756 let res = unsafe {
757 ffi::cmap_track_add(
758 handle.cmap_handle,
759 c_name.as_ptr(),
760 track_type.bits(),
761 Some(rust_notify_fn),
762 user_data as *mut c_void,
763 &mut c_trackhandle,
764 )
765 };
766 if res == ffi::CS_OK {
767 let rhandle = TrackHandle {
768 track_handle: c_trackhandle,
769 notify_callback: *notify_callback,
770 };
771 TRACKHANDLE_HASH
772 .lock()
773 .unwrap()
774 .insert(c_trackhandle, rhandle);
775 Ok(rhandle)
776 } else {
777 Err(CsError::from_c(res))
778 }
779}
780
781pub fn track_delete(handle: &Handle, track_handle: TrackHandle) -> Result<()> {
783 let res = unsafe { ffi::cmap_track_delete(handle.cmap_handle, track_handle.track_handle) };
784 if res == ffi::CS_OK {
785 TRACKHANDLE_HASH
786 .lock()
787 .unwrap()
788 .remove(&track_handle.track_handle);
789 Ok(())
790 } else {
791 Err(CsError::from_c(res))
792 }
793}
794
795pub struct CmapIterStart {
797 iter_handle: u64,
798 cmap_handle: u64,
799}
800
801pub struct CmapIntoIter {
802 cmap_handle: u64,
803 iter_handle: u64,
804}
805
806pub struct CmapIter {
808 key_name: String,
809 data: Data,
810}
811
812impl CmapIter {
813 pub fn key_name(&self) -> &str {
814 &self.key_name
815 }
816 pub fn data(&self) -> &Data {
817 &self.data
818 }
819}
820
821impl fmt::Debug for CmapIter {
822 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823 write!(f, "{}: {}", self.key_name, self.data)
824 }
825}
826
827impl Iterator for CmapIntoIter {
828 type Item = CmapIter;
829
830 fn next(&mut self) -> Option<CmapIter> {
831 let mut c_key_name = [0u8; CMAP_KEYNAME_MAXLENGTH + 1];
832 let mut c_value_len = 0usize;
833 let mut c_value_type = 0u32;
834 let res = unsafe {
835 ffi::cmap_iter_next(
836 self.cmap_handle,
837 self.iter_handle,
838 c_key_name.as_mut_ptr() as *mut c_char,
839 &mut c_value_len,
840 &mut c_value_type,
841 )
842 };
843 if res == ffi::CS_OK {
844 let mut c_value = vec![0u8; c_value_len];
846 let res = unsafe {
847 ffi::cmap_get(
848 self.cmap_handle,
849 c_key_name.as_ptr() as *mut c_char,
850 c_value.as_mut_ptr() as *mut c_void,
851 &mut c_value_len,
852 &mut c_value_type,
853 )
854 };
855 if res == ffi::CS_OK {
856 match c_to_data(c_value_len, c_value_type, c_value.as_ptr()) {
857 Ok(d) => {
858 let r_keyname = match string_from_bytes(
859 c_key_name.as_ptr() as *mut c_char,
860 CMAP_KEYNAME_MAXLENGTH,
861 ) {
862 Ok(s) => s,
863 Err(_) => return None,
864 };
865 Some(CmapIter {
866 key_name: r_keyname,
867 data: d,
868 })
869 }
870 Err(_) => None,
871 }
872 } else {
873 None
875 }
876 } else if res == ffi::CS_ERR_NO_SECTIONS {
877 unsafe {
879 ffi::cmap_iter_finalize(self.cmap_handle, self.iter_handle)
881 };
882 None
883 } else {
884 None
885 }
886 }
887}
888
889impl CmapIterStart {
890 pub fn new(cmap_handle: &Handle, prefix: &str) -> Result<CmapIterStart> {
892 let mut iter_handle: u64 = 0;
893 let res = unsafe {
894 let c_prefix = string_to_cstring_validated(prefix, CMAP_KEYNAME_MAXLENGTH)?;
895 ffi::cmap_iter_init(cmap_handle.cmap_handle, c_prefix.as_ptr(), &mut iter_handle)
896 };
897 if res == ffi::CS_OK {
898 Ok(CmapIterStart {
899 cmap_handle: cmap_handle.cmap_handle,
900 iter_handle,
901 })
902 } else {
903 Err(CsError::from_c(res))
904 }
905 }
906}
907
908impl IntoIterator for CmapIterStart {
909 type Item = CmapIter;
910 type IntoIter = CmapIntoIter;
911
912 fn into_iter(self) -> Self::IntoIter {
913 CmapIntoIter {
914 iter_handle: self.iter_handle,
915 cmap_handle: self.cmap_handle,
916 }
917 }
918}