Skip to content

Commit

Permalink
Add XmpMeta::compose_array_item_path (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe authored Oct 27, 2022
1 parent 7df67b9 commit fc8b896
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,30 @@ extern "C" {
#endif
}

const char* CXmpMetaComposeArrayItemPath(CXmpError* outError,
const char* schemaNS,
const char* arrayName,
AdobeXMPCommon::int32 index) {
#ifndef NOOP_FFI
try {
std::string resultPath;
SXMPUtils::ComposeArrayItemPath(schemaNS,
arrayName,
index,
&resultPath);

return copyStringForResult(resultPath);
}
catch (XMP_Error& e) {
copyErrorForResult(e, outError);
}
catch (...) {
signalUnknownError(outError);
}
#endif

return NULL;
}

const char* CXmpMetaComposeStructFieldPath(CXmpError* outError,
const char* schemaNS,
Expand Down
7 changes: 7 additions & 0 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,13 @@ extern "C" {
name: *const c_char,
);

pub(crate) fn CXmpMetaComposeArrayItemPath(
out_error: *mut CXmpError,
schema_ns: *const c_char,
array_name: *const c_char,
index: i32,
) -> *const c_char;

pub(crate) fn CXmpMetaComposeStructFieldPath(
out_error: *mut CXmpError,
schema_ns: *const c_char,
Expand Down
37 changes: 37 additions & 0 deletions src/tests/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,43 @@ mod name {
}
}

mod compose_array_index_path {
use crate::{xmp_ns, XmpErrorType, XmpMeta};

#[test]
fn happy_path() {
assert_eq!(
XmpMeta::compose_array_item_path(xmp_ns::XMP, "ArrayName", 4).unwrap(),
"ArrayName[4]"
);
}

#[test]
fn last_item() {
assert_eq!(
XmpMeta::compose_array_item_path(xmp_ns::XMP, "ArrayName", XmpMeta::LAST_ITEM).unwrap(),
"ArrayName[last()]"
);
}

#[test]
fn zero_index() {
// This isn't technically allowed, but C++ XMP Toolkit doesn't flag it.
assert_eq!(
XmpMeta::compose_array_item_path(xmp_ns::XMP, "ArrayName", 0).unwrap(),
"ArrayName[0]"
);
}

#[test]
fn negative_index() {
let err = XmpMeta::compose_array_item_path(xmp_ns::XMP, "ArrayName", -4).unwrap_err();

assert_eq!(err.error_type, XmpErrorType::BadParam);
assert_eq!(err.debug_message, "Array index out of bounds");
}
}

mod compose_struct_field_path {
use crate::{xmp_ns, XmpMeta};

Expand Down
42 changes: 42 additions & 0 deletions src/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ impl Drop for XmpMeta {
}

impl XmpMeta {
/// Special index value which references the last item in an array,
/// regardless of the array index.
pub const LAST_ITEM: i32 = -1;

/// Creates a new, empty metadata struct.
///
/// An error result from this function is unlikely but possible
Expand Down Expand Up @@ -1005,6 +1009,44 @@ impl XmpMeta {
}
}

/// Composes the path expression for an item in an array.
///
/// ## Arguments
///
/// * `array_ns` and `array_path`: See [Accessing
/// properties](#accessing-properties).
/// * `item_index`: The index of the desired item. Use
/// [`XmpMeta::LAST_ITEM`] to specify the last existing array item.
/// **IMPORTANT:** Indices in XMP are 1-based, not zero-based as in most
/// of Rust.
///
/// ## Return
///
/// If successful, the returned string is in the form
/// `array_name[array_index]`.
pub fn compose_array_item_path(
array_ns: &str,
array_path: &str,
index: i32,
) -> XmpResult<String> {
let c_array_ns = CString::new(array_ns).unwrap_or_default();
let c_array_name = CString::new(array_path).unwrap_or_default();

let mut err = ffi::CXmpError::default();

unsafe {
let result = CXmpString::from_ptr(ffi::CXmpMetaComposeArrayItemPath(
&mut err,
c_array_ns.as_ptr(),
c_array_name.as_ptr(),
index,
));

XmpError::raise_from_c(&err)?;
Ok(result.as_string())
}
}

/// Composes the path expression for a field in a struct.
///
/// ## Arguments
Expand Down

0 comments on commit fc8b896

Please sign in to comment.