Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace XmpMeta::from_str_requiring_xmp_meta with XmpMeta::from_str_with_options #137

Merged
merged 2 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod xmp_value;
pub use xmp_date_time::{XmpDate, XmpDateTime, XmpTime, XmpTimeZone};
pub use xmp_error::{XmpError, XmpErrorType, XmpResult};
pub use xmp_file::{OpenFileOptions, XmpFile};
pub use xmp_meta::{ArrayProperty, ItemPlacement, ToStringOptions, XmpMeta};
pub use xmp_meta::{ArrayProperty, FromStrOptions, ItemPlacement, ToStringOptions, XmpMeta};
pub use xmp_value::XmpValue;

#[cfg(test)]
Expand Down
24 changes: 24 additions & 0 deletions src/tests/fixtures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,27 @@ pub(crate) const LOCALIZED_TEXT_EXAMPLE: &str = r#"<rdf:RDF xmlns:rdf="http://ww
</dc:title>
</rdf:Description>
</rdf:RDF>"#;

pub(crate) const INCONSISTENT_RDF: &str = r#"<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about='Test:XMPCoreCoverage/kInconsistentRDF'
xmlns:pdf='http://ns.adobe.com/pdf/1.3/'
xmlns:xmp='http://ns.adobe.com/xap/1.0/'
xmlns:dc='http://purl.org/dc/elements/1.1/'>

<pdf:Author>PDF Author</pdf:Author>
<xmp:Author>XMP Author</xmp:Author>

<xmp:Authors>
<rdf:Seq>
<rdf:li>XMP Authors [1]</rdf:li>
</rdf:Seq>
</xmp:Authors>

<dc:creator>
<rdf:Seq>
<rdf:li>DC Creator [1]</rdf:li>
</rdf:Seq>
</dc:creator>

</rdf:Description>
</rdf:RDF>"#;
47 changes: 39 additions & 8 deletions src/tests/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ mod from_str {
}
}

mod from_str_requiring_xmp_meta {
use crate::{tests::fixtures::*, XmpMeta, XmpValue};
mod from_str_with_options {
use crate::{tests::fixtures::*, FromStrOptions, XmpError, XmpErrorType, XmpMeta, XmpValue};

const NO_META: &str = r#"<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about=""
Expand Down Expand Up @@ -215,8 +215,9 @@ mod from_str_requiring_xmp_meta {
"#;

#[test]
fn happy_path() {
let m = XmpMeta::from_str_requiring_xmp_meta(PURPLE_SQUARE_XMP, false).unwrap();
fn default_options() {
let m =
XmpMeta::from_str_with_options(PURPLE_SQUARE_XMP, FromStrOptions::default()).unwrap();

assert_eq!(
m.property("http://ns.adobe.com/xap/1.0/", "CreatorTool")
Expand Down Expand Up @@ -246,7 +247,11 @@ mod from_str_requiring_xmp_meta {
// TODO (https://github.com/adobe/xmp-toolkit-rs/issues/135):
// I think this should be an error response, not a silent
// Ok(default) response.
assert!(XmpMeta::from_str_requiring_xmp_meta(NO_META, true).is_ok());
assert!(XmpMeta::from_str_with_options(
NO_META,
FromStrOptions::default().require_xmp_meta()
)
.is_ok());

// Should be:
// XmpError {
Expand All @@ -257,7 +262,7 @@ mod from_str_requiring_xmp_meta {

#[test]
fn missing_xmp_meta_not_required() {
let m = XmpMeta::from_str_requiring_xmp_meta(NO_META, false).unwrap();
let m = XmpMeta::from_str_with_options(NO_META, FromStrOptions::default()).unwrap();

println!("m = {:#?}", m);

Expand All @@ -284,12 +289,38 @@ mod from_str_requiring_xmp_meta {
.is_none());
}

#[test]
fn strict_aliasing_should_fail() {
assert_eq!(
XmpMeta::from_str_with_options(
INCONSISTENT_RDF,
FromStrOptions::default().strict_aliasing()
)
.unwrap_err(),
XmpError {
error_type: XmpErrorType::BadXmp,
debug_message: "Mismatch between alias and base nodes".to_owned()
}
);
}

#[test]
fn strict_aliasing_ignore() {
assert_eq!(
XmpMeta::from_str_with_options(INCONSISTENT_RDF, FromStrOptions::default())
.unwrap()
.to_string(),
"<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 6.0.0\"> <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> <rdf:Description rdf:about=\"Test:XMPCoreCoverage/kInconsistentRDF\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\"> <dc:creator> <rdf:Seq> <rdf:li>DC Creator [1]</rdf:li> </rdf:Seq> </dc:creator> </rdf:Description> </rdf:RDF> </x:xmpmeta>"
);
}

#[test]
fn bad_xmp() {
// TXMPMeta::ParseFromBuffer doesn't seem to throw exceptions,
// regardless of how badly-formed the XMP is. This test merely
// confirms that we pass that behavior through.
let m = XmpMeta::from_str_requiring_xmp_meta("this is not XMP", false).unwrap();
let m =
XmpMeta::from_str_with_options("this is not XMP", FromStrOptions::default()).unwrap();

assert!(m
.property("http://ns.adobe.com/xap/1.0/", "CreatorTool")
Expand All @@ -309,7 +340,7 @@ mod from_str_requiring_xmp_meta {
// TXMPMeta::ParseFromBuffer doesn't seem to throw exceptions,
// regardless of how badly-formed the XMP is. This test merely
// confirms that we pass that behavior through.
let m = XmpMeta::from_str_requiring_xmp_meta("", false).unwrap();
let m = XmpMeta::from_str_with_options("", FromStrOptions::default()).unwrap();

assert!(m
.property("http://ns.adobe.com/xap/1.0/", "CreatorTool")
Expand Down
43 changes: 33 additions & 10 deletions src/xmp_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1668,20 +1668,17 @@ impl XmpMeta {
/// Creates a new `XmpMeta` struct and populates it with metadata from a
/// string containing serialized RDF. This string must be a complete RDF
/// parse stream.
///
/// ## Arguments
///
/// * `s`: XMP string to be read
/// * `require_xmp_meta`: if `true`, the `x:xmpmeta` XML element is required
/// around `rdf:RDF`
pub fn from_str_requiring_xmp_meta(s: &str, require_xmp_meta: bool) -> XmpResult<Self> {
pub fn from_str_with_options(s: &str, options: FromStrOptions) -> XmpResult<Self> {
let mut err = ffi::CXmpError::default();
let bytes = s.as_bytes();

let options = if require_xmp_meta { 1 } else { 0 };

let m = unsafe {
ffi::CXmpMetaParseFromBuffer(&mut err, bytes.as_ptr(), bytes.len() as u32, options)
ffi::CXmpMetaParseFromBuffer(
&mut err,
bytes.as_ptr(),
bytes.len() as u32,
options.options,
)
};

XmpError::raise_from_c(&err)?;
Expand Down Expand Up @@ -1862,6 +1859,32 @@ pub(crate) fn no_cpp_toolkit() -> XmpError {
}
}

/// Provides options for configuring the XMP parsing behavior
/// provided by [`XmpMeta::from_str_with_options`].
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct FromStrOptions {
pub(crate) options: u32,
}

impl FromStrOptions {
pub(crate) const REQUIRE_XMP_META: u32 = 0x0001;
// pub(crate) const PARSE_MORE_BUFFERS: u32 = 0x0002;
pub(crate) const STRICT_ALIASING: u32 = 0x0004;

/// Require a surrounding `x:xmpmeta` element.
pub fn require_xmp_meta(mut self) -> Self {
self.options |= Self::REQUIRE_XMP_META;
self
}

/// Do not reconcile alias differences. If differences are found,
/// return an `Err` result.
pub fn strict_aliasing(mut self) -> Self {
self.options |= Self::STRICT_ALIASING;
self
}
}

/// Provides options for configuring the XMP serialization behavior
/// provided by [`XmpMeta::to_string_with_options`].
///
Expand Down