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