diff --git a/src/ffi.cpp b/src/ffi.cpp index bb03bce..78f3f41 100644 --- a/src/ffi.cpp +++ b/src/ffi.cpp @@ -744,6 +744,29 @@ extern "C" { #endif } + bool CXmpMetaCountArrayItems(CXmpMeta* m, + CXmpError* outError, + const char* arrayNS, + const char* arrayName, + AdobeXMPCommon::uint32* outValue) { + *outValue = 0; + + #ifndef NOOP_FFI + try { + *outValue = m->m.CountArrayItems(arrayNS, arrayName); + return true; + } + catch (XMP_Error& e) { + copyErrorForResult(e, outError); + } + catch (...) { + signalUnknownError(outError); + } + #endif + + return false; + } + const char* CXmpMetaGetStructField(CXmpMeta* m, CXmpError* outError, const char* schemaNS, diff --git a/src/ffi.rs b/src/ffi.rs index 2fbabfa..36e5f75 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -336,6 +336,14 @@ extern "C" { item_options: u32, ); + pub(crate) fn CXmpMetaCountArrayItems( + meta: *const CXmpMeta, + out_error: *mut CXmpError, + array_ns: *const c_char, + array_name: *const c_char, + count: *mut u32, + ) -> bool; + pub(crate) fn CXmpMetaSetStructField( meta: *mut CXmpMeta, out_error: *mut CXmpError, diff --git a/src/tests/xmp_meta.rs b/src/tests/xmp_meta.rs index b0b718d..faf40cb 100644 --- a/src/tests/xmp_meta.rs +++ b/src/tests/xmp_meta.rs @@ -1906,6 +1906,49 @@ mod append_array_item { } } +mod array_len { + use std::str::FromStr; + + use crate::{tests::fixtures::*, XmpMeta}; + + #[test] + fn happy_path_creator_seq() { + let m = XmpMeta::from_str(PURPLE_SQUARE_XMP).unwrap(); + assert_eq!( + m.array_len("http://purl.org/dc/elements/1.1/", "creator"), + 1 + ); + } + + #[test] + fn happy_path_creator_bag() { + let m = XmpMeta::from_str(PURPLE_SQUARE_XMP).unwrap(); + assert_eq!( + m.array_len("http://purl.org/dc/elements/1.1/", "subject"), + 6 + ); + } + + #[test] + fn init_fail() { + let m = XmpMeta::new_fail(); + assert_eq!( + m.array_len("http://purl.org/dc/elements/1.1/", "creator"), + 0 + ); + } + + #[test] + fn no_such_property() { + let m = XmpMeta::from_str(PURPLE_SQUARE_XMP).unwrap(); + + assert_eq!( + m.array_len("http://purl.org/dc/elements/1.1/", "creatorx"), + 0 + ); + } +} + mod set_struct_field { use std::str::FromStr; diff --git a/src/xmp_meta.rs b/src/xmp_meta.rs index 8f6fb94..78e80a7 100644 --- a/src/xmp_meta.rs +++ b/src/xmp_meta.rs @@ -899,6 +899,37 @@ impl XmpMeta { } } + /// Reports the number of items currently defined in an array. + /// + /// ## Arguments + /// + /// * `array_ns` and `array_name`: See [Accessing + /// properties](#accessing-properties). + /// + /// If any error occurs (for instance, the array does not exist), + /// this function will return 0. + pub fn array_len(&self, array_ns: &str, array_name: &str) -> usize { + let mut result: u32 = 0; + + if let Some(m) = self.m { + let c_array_ns = CString::new(array_ns).unwrap_or_default(); + let c_array_name = CString::new(array_name.as_bytes()).unwrap_or_default(); + let mut err = ffi::CXmpError::default(); + + unsafe { + ffi::CXmpMetaCountArrayItems( + m, + &mut err, + c_array_ns.as_ptr(), + c_array_name.as_ptr(), + &mut result, + ); + } + } + + result as usize + } + /// Creates or sets the value of a field within a nested structure, /// using a string value. ///