1use std::{
6 ffi::{CStr, CString},
7 ptr,
8};
9
10use libc::c_char;
11
12use crate::{err::BlkidErr, Result};
13
14pub struct BlkidTagIter(libblkid_rs_sys::blkid_tag_iterate);
16
17impl BlkidTagIter {
18 pub(crate) fn new(iter: libblkid_rs_sys::blkid_tag_iterate) -> Self {
19 BlkidTagIter(iter)
20 }
21}
22
23impl Iterator for BlkidTagIter {
24 type Item = (String, String);
25
26 fn next(&mut self) -> Option<Self::Item> {
27 let mut type_: *const c_char = ptr::null_mut();
28 let mut value: *const c_char = ptr::null_mut();
29 if unsafe {
30 libblkid_rs_sys::blkid_tag_next(
31 self.0,
32 &mut type_ as *mut *const _,
33 &mut value as *mut *const _,
34 )
35 } < 0
36 {
37 None
38 } else {
39 assert!(!type_.is_null() && !value.is_null());
40 let type_str = unsafe { CStr::from_ptr(type_) };
41 let value_str = unsafe { CStr::from_ptr(value) };
42 Some((
43 type_str.to_str().ok()?.to_string(),
44 value_str.to_str().ok()?.to_string(),
45 ))
46 }
47 }
48}
49
50impl Drop for BlkidTagIter {
51 fn drop(&mut self) {
52 unsafe { libblkid_rs_sys::blkid_tag_iterate_end(self.0) }
53 }
54}
55
56pub fn parse_tag_string(tag_string: &str) -> Result<(String, String)> {
58 let tag_cstring = CString::new(tag_string)?;
59 let mut type_: *mut c_char = ptr::null_mut();
60 let mut value: *mut c_char = ptr::null_mut();
61 let ret = unsafe {
62 libblkid_rs_sys::blkid_parse_tag_string(
63 tag_cstring.as_ptr(),
64 &mut type_ as *mut *mut _,
65 &mut value as *mut *mut _,
66 )
67 };
68 if ret < 0 {
69 Err(BlkidErr::LibErr(i64::from(ret)))
70 } else {
71 assert!(!type_.is_null() && !value.is_null());
72 let type_str = unsafe { CStr::from_ptr(type_) };
73 let value_str = unsafe { CStr::from_ptr(value) };
74 Ok((
75 type_str.to_str()?.to_string(),
76 value_str.to_str()?.to_string(),
77 ))
78 }
79}