use std::{ffi::CString, os::raw::c_char};
use crate::{
ffi::{self, CXmpString},
XmpMeta, XmpValue,
};
pub struct XmpIterator<'a> {
#[allow(dead_code)]
pub(crate) m: &'a XmpMeta,
pub(crate) i: *mut ffi::CXmpIterator,
}
impl<'a> XmpIterator<'a> {
pub(crate) fn new(meta: &'a XmpMeta, options: IterOptions) -> Self {
let mut err = ffi::CXmpError::default();
if let Some(m) = meta.m {
let c_schema_ns = CString::new(options.schema_ns).unwrap_or_default();
let c_prop_name = CString::new(options.prop_name).unwrap_or_default();
unsafe {
Self {
m: meta,
i: ffi::CXmpIteratorNew(
m,
&mut err,
c_schema_ns.as_ptr(),
c_prop_name.as_ptr(),
options.options,
),
}
}
} else {
Self {
m: meta,
i: std::ptr::null_mut(),
}
}
}
pub fn skip_subtree(&mut self) {
if !self.i.is_null() {
unsafe {
let mut err = ffi::CXmpError::default();
ffi::CXmpIteratorSkip(self.i, &mut err, 1);
}
}
}
pub fn skip_siblings(&mut self) {
if !self.i.is_null() {
unsafe {
let mut err = ffi::CXmpError::default();
ffi::CXmpIteratorSkip(self.i, &mut err, 2);
}
}
}
}
impl Drop for XmpIterator<'_> {
fn drop(&mut self) {
unsafe {
ffi::CXmpIteratorDrop(self.i);
}
}
}
impl Iterator for XmpIterator<'_> {
type Item = XmpProperty;
fn next(&mut self) -> Option<Self::Item> {
if !self.i.is_null() {
unsafe {
let mut err = ffi::CXmpError::default();
let mut c_schema_ns: *const c_char = std::ptr::null_mut();
let mut c_prop_path: *const c_char = std::ptr::null_mut();
let mut c_prop_value: *const c_char = std::ptr::null_mut();
let mut options: u32 = 0;
if ffi::CXmpIteratorNext(
self.i,
&mut err,
&mut c_schema_ns,
&mut c_prop_path,
&mut c_prop_value,
&mut options,
) {
Some(XmpProperty {
schema_ns: CXmpString::from_ptr(c_schema_ns).as_string(),
name: CXmpString::from_ptr(c_prop_path).as_string(),
value: XmpValue {
value: CXmpString::from_ptr(c_prop_value).as_string(),
options,
},
})
} else {
None
}
}
} else {
None
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct IterOptions {
pub(crate) schema_ns: String,
pub(crate) prop_name: String,
pub(crate) options: u32,
}
impl IterOptions {
const JUST_CHILDREN: u32 = 0x0100;
const JUST_LEAF_NAME: u32 = 0x0400;
const JUST_LEAF_NODES: u32 = 0x0200;
const OMIT_QUALIFIERS: u32 = 0x1000;
pub fn schema_ns(mut self, schema_ns: &str) -> Self {
schema_ns.clone_into(&mut self.schema_ns);
self.prop_name = String::default();
self
}
pub fn property(mut self, schema_ns: &str, prop_name: &str) -> Self {
schema_ns.clone_into(&mut self.schema_ns);
prop_name.clone_into(&mut self.prop_name);
self
}
pub fn immediate_children_only(mut self) -> Self {
self.options |= Self::JUST_CHILDREN;
self
}
pub fn leaf_nodes_only(mut self) -> Self {
self.options |= Self::JUST_LEAF_NODES;
self
}
pub fn leaf_name_only(mut self) -> Self {
self.options |= Self::JUST_LEAF_NAME;
self
}
pub fn omit_qualifiers(mut self) -> Self {
self.options |= Self::OMIT_QUALIFIERS;
self
}
}
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct XmpProperty {
pub schema_ns: String,
pub name: String,
pub value: XmpValue<String>,
}