Skip to content

Commit

Permalink
Add XmpMeta::append_array_item (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe authored Oct 25, 2022
1 parent 01ef0c4 commit a2e8291
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,27 @@ extern "C" {
#endif
}

void CXmpMetaAppendArrayItem(CXmpMeta* m,
CXmpError* outError,
const char* schemaNS,
const char* arrayName,
AdobeXMPCommon::uint32 arrayOptions,
const char* itemValue,
AdobeXMPCommon::uint32 itemOptions) {
#ifndef NOOP_FFI
try {
m->m.AppendArrayItem(schemaNS, arrayName, arrayOptions, itemValue, itemOptions);
}
catch (XMP_Error& e) {
copyErrorForResult(e, outError);
}
catch (...) {
signalUnknownError(outError);
}
#endif
}


const char* CXmpMetaGetStructField(CXmpMeta* m,
CXmpError* outError,
const char* schemaNS,
Expand Down
10 changes: 10 additions & 0 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,16 @@ extern "C" {
options: u32,
);

pub(crate) fn CXmpMetaAppendArrayItem(
meta: *mut CXmpMeta,
out_error: *mut CXmpError,
schema_ns: *const c_char,
array_name: *const c_char,
array_options: u32,
item_value: *const c_char,
item_options: u32,
);

pub(crate) fn CXmpMetaDoesPropertyExist(
meta: *const CXmpMeta,
schema_ns: *const c_char,
Expand Down
130 changes: 130 additions & 0 deletions src/tests/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,136 @@ mod set_property_date {
}
}

mod append_array_item {
use crate::{xmp_ns, xmp_value::xmp_prop, XmpErrorType, XmpMeta, XmpValue};

#[test]
fn happy_path() {
let mut m = XmpMeta::default();

m.append_array_item(
xmp_ns::DC,
&XmpValue::from("creator").set_is_ordered(true),
&XmpValue::from("Author 1"),
)
.unwrap();

m.append_array_item(
xmp_ns::DC,
&XmpValue::from("creator").set_is_ordered(true),
&XmpValue::from("Author 2"),
)
.unwrap();

assert_eq!(
m.property(xmp_ns::DC, "creator").unwrap(),
XmpValue {
value: "".to_owned(),
options: xmp_prop::VALUE_IS_ARRAY | xmp_prop::ARRAY_IS_ORDERED
}
);

let creators: Vec<XmpValue<String>> = m.property_array(xmp_ns::DC, "creator").collect();
println!("creators = {:#?}", creators);

let mut creators_iter = creators.iter();

let creator = creators_iter.next().unwrap();
assert_eq!(creator.value, "Author 1");
assert_eq!(creator.options, 0);

let creator = creators_iter.next().unwrap();
assert_eq!(creator.value, "Author 2");
assert_eq!(creator.options, 0);

assert_eq!(creators_iter.next(), None);
}

#[test]
fn item_options() {
let mut m = XmpMeta::default();

m.append_array_item(
xmp_ns::DC,
&XmpValue::from("creator").set_is_ordered(true),
&XmpValue::from("Author 1"),
)
.unwrap();

m.append_array_item(
xmp_ns::DC,
&XmpValue::from("creator").set_is_ordered(true),
&XmpValue::from("Author 2").set_is_uri(true),
)
.unwrap();

let creators: Vec<XmpValue<String>> = m.property_array(xmp_ns::DC, "creator").collect();
println!("creators = {:#?}", creators);

let mut creators_iter = creators.iter();

let creator = creators_iter.next().unwrap();
assert_eq!(creator.value, "Author 1");
assert_eq!(creator.options, 0);

let creator = creators_iter.next().unwrap();
assert_eq!(creator.value, "Author 2");
assert_eq!(creator.options, xmp_prop::VALUE_IS_URI);

assert_eq!(creators_iter.next(), None);
}

#[test]
fn init_fail() {
let mut m = XmpMeta::new_fail();

let err = m
.append_array_item(
xmp_ns::DC,
&XmpValue::from("creator").set_is_ordered(true),
&XmpValue::from("Author 1"),
)
.unwrap_err();

assert_eq!(err.error_type, XmpErrorType::NoCppToolkit);
}

#[test]
fn error_empty_array_name() {
let mut m = XmpMeta::default();

let err = m
.append_array_item(
xmp_ns::DC,
&XmpValue::from("").set_is_ordered(true),
&XmpValue::from("Author 1"),
)
.unwrap_err();

assert_eq!(err.error_type, XmpErrorType::BadXPath);
assert_eq!(err.debug_message, "Empty array name");
}

#[test]
fn error_nul_in_name() {
let mut m = XmpMeta::default();

let err = m
.append_array_item(
xmp_ns::DC,
&XmpValue::from("x\0x").set_is_ordered(true),
&XmpValue::from("Author 1"),
)
.unwrap_err();

assert_eq!(err.error_type, XmpErrorType::NulInRustString);
assert_eq!(
err.debug_message,
"Unable to convert to C string because a NUL byte was found"
);
}
}

mod localized_text {
use std::str::FromStr;

Expand Down
48 changes: 48 additions & 0 deletions src/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,54 @@ impl XmpMeta {
}
}

/// Adds an item to an array, creating the array if necessary.
///
/// This function simplifies construction of an array by not requiring
/// that you pre-create an empty array. The array that is assigned is
/// created automatically if it does not yet exist. If the array exists,
/// it must have the form specified by the flags on `array_name`.
///
/// Each call appends a new item to the array.
///
/// Use `XmpMeta::compose_array_item_path()` to create a complex path.
///
/// ## Arguments
///
/// * `namespace` and `array_name`: See [Accessing
/// properties](#accessing-properties). NOTE: `array_name` is an
/// `XmpValue<String>` which contains any necessary flags for the array.
/// * `item_value`: Contains value and flags for the item to be added to the
/// array.
pub fn append_array_item(
&mut self,
namespace: &str,
array_name: &XmpValue<String>,
item_value: &XmpValue<String>,
) -> XmpResult<()> {
if let Some(m) = self.m {
let c_ns = CString::new(namespace)?;
let c_array_name = CString::new(array_name.value.as_bytes())?;
let c_item_value = CString::new(item_value.value.as_bytes())?;
let mut err = ffi::CXmpError::default();

unsafe {
ffi::CXmpMetaAppendArrayItem(
m,
&mut err,
c_ns.as_ptr(),
c_array_name.as_ptr(),
array_name.options,
c_item_value.as_ptr(),
item_value.options,
);
}

XmpError::raise_from_c(&err)
} else {
Err(no_cpp_toolkit())
}
}

/// Retrieves information about a selected item from an alt-text array.
///
/// Localized text properties are stored in alt-text arrays. They allow
Expand Down

0 comments on commit a2e8291

Please sign in to comment.