[niepce/lr-import: 11/20] Update to exempi2




commit 0dda6a7a9e86d52d54dfd38fea8b22007a6a7bdc
Author: Hubert Figuière <hub figuiere net>
Date:   Sun Dec 5 21:20:48 2021 -0500

    Update to exempi2

 Cargo.lock                              |  24 +++---
 crates/npc-engine/Cargo.toml            |   2 +-
 crates/npc-engine/src/db/libmetadata.rs | 124 +++++++++++++++------------
 crates/npc-engine/src/db/library.rs     |   4 +-
 crates/npc-fwk/Cargo.toml               |   2 +-
 crates/npc-fwk/src/base/date.rs         |   8 +-
 crates/npc-fwk/src/lib.rs               |   2 +-
 crates/npc-fwk/src/utils/exempi.rs      | 147 ++++++++++++++------------------
 crates/npc-fwk/src/utils/exiv2.rs       |  32 +++----
 9 files changed, 172 insertions(+), 173 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index f7874ed..1cb9755 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -221,22 +221,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
 
 [[package]]
-name = "exempi"
-version = "2.6.0"
-source = 
"git+https://github.com/hfiguiere/exempi-rs.git?rev=99e8ba5#99e8ba58318d693bdc7aecce1ca6375a3e11d89f";
+name = "exempi-sys"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "092ed317836115f2a074e1fcc8ed9b2ced33bc7af1e71512cd4aa3a5be696e37"
 dependencies = [
- "bitflags",
- "exempi-sys",
  "libc",
+ "pkg-config",
 ]
 
 [[package]]
-name = "exempi-sys"
-version = "2.5.0"
-source = 
"git+https://github.com/hfiguiere/exempi-rs.git?rev=99e8ba5#99e8ba58318d693bdc7aecce1ca6375a3e11d89f";
+name = "exempi2"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "1deb5527e7a45f3ac714fc6cb78fa40e2be21a39824c93280deb71877216aa7d"
 dependencies = [
+ "bitflags",
+ "exempi-sys",
  "libc",
- "pkg-config",
 ]
 
 [[package]]
@@ -774,7 +776,7 @@ dependencies = [
  "cbindgen",
  "chrono",
  "clap",
- "exempi",
+ "exempi2",
  "gdk-pixbuf",
  "gdk-pixbuf-sys",
  "gettext-rs 0.7.0",
@@ -795,7 +797,7 @@ dependencies = [
  "cairo-rs",
  "cbindgen",
  "chrono",
- "exempi",
+ "exempi2",
  "gdk",
  "gdk-pixbuf",
  "gdk-pixbuf-sys",
diff --git a/crates/npc-engine/Cargo.toml b/crates/npc-engine/Cargo.toml
index 2425eaf..69c5c1a 100644
--- a/crates/npc-engine/Cargo.toml
+++ b/crates/npc-engine/Cargo.toml
@@ -13,7 +13,7 @@ license = "GPL-3.0"
 async-channel = "1.6.1"
 clap = { version = "2.33.3", optional = true }
 chrono = "0.4.19"
-exempi = { version = "2.6.0", git = "https://github.com/hfiguiere/exempi-rs.git";, rev="99e8ba5" }
+exempi2 = { version = "0.1.1" }
 gettext-rs = "0.7.0"
 gdk-pixbuf-sys = "*"
 gdk-pixbuf = "*"
diff --git a/crates/npc-engine/src/db/libmetadata.rs b/crates/npc-engine/src/db/libmetadata.rs
index f7d305d..30e71aa 100644
--- a/crates/npc-engine/src/db/libmetadata.rs
+++ b/crates/npc-engine/src/db/libmetadata.rs
@@ -29,11 +29,16 @@ use npc_fwk::{xmp_date_from, PropertyBag, PropertySet, PropertyValue, XmpMeta};
 
 #[derive(Clone)]
 pub struct LibMetadata {
-    xmp: XmpMeta,
+    /// The XmpMeta block
+    xmp_meta: XmpMeta,
+    /// Library ID this is associated to.
     id: LibraryId,
+    /// List of sidecards
     pub sidecars: Vec<String>,
     pub file_type: FileType,
+    /// name to be displayed
     pub name: String,
+    /// Folder name for display
     pub folder: String,
 }
 
@@ -52,7 +57,7 @@ fn property_index_to_xmp(meta: Np) -> Option<IndexToXmp> {
 impl LibMetadata {
     pub fn new(id: LibraryId) -> LibMetadata {
         LibMetadata {
-            xmp: XmpMeta::new(),
+            xmp_meta: XmpMeta::new(),
             id,
             sidecars: vec![],
             file_type: FileType::Unknown,
@@ -61,9 +66,10 @@ impl LibMetadata {
         }
     }
 
-    pub fn new_with_xmp(id: LibraryId, xmp: XmpMeta) -> LibMetadata {
+    /// Create a LibMetadata with an XmpMeta.
+    pub fn new_with_xmp(id: LibraryId, xmp_meta: XmpMeta) -> LibMetadata {
         LibMetadata {
-            xmp,
+            xmp_meta,
             id,
             sidecars: vec![],
             file_type: FileType::Unknown,
@@ -73,19 +79,20 @@ impl LibMetadata {
     }
 
     pub fn serialize_inline(&self) -> String {
-        self.xmp.serialize_inline()
+        self.xmp_meta.serialize_inline()
     }
 
     fn get_metadata(&self, meta: Np) -> Option<PropertyValue> {
         let index_to_xmp = property_index_to_xmp(meta)?;
 
-        let mut prop_flags = exempi::PropFlags::default();
-        let mut xmp_result =
-            self.xmp
-                .xmp
-                .get_property(&index_to_xmp.ns, &index_to_xmp.property, &mut prop_flags);
-        if xmp_result.is_ok() && prop_flags.contains(exempi::PropFlags::ARRAY_IS_ALTTEXT) {
-            if let Ok((_, value)) = self.xmp.xmp.get_localized_text(
+        let mut prop_flags = exempi2::PropFlags::default();
+        let mut xmp_result = self.xmp_meta.xmp.get_property(
+            &index_to_xmp.ns,
+            &index_to_xmp.property,
+            &mut prop_flags,
+        );
+        if xmp_result.is_ok() && prop_flags.contains(exempi2::PropFlags::ARRAY_IS_ALTTEXT) {
+            if let Ok((_, value)) = self.xmp_meta.xmp.get_localized_text(
                 &index_to_xmp.ns,
                 &index_to_xmp.property,
                 "",
@@ -95,36 +102,42 @@ impl LibMetadata {
                 xmp_result = Ok(value);
             }
         }
-        Some(PropertyValue::String(String::from(
-            xmp_result.ok()?.to_str(),
-        )))
+        Some(PropertyValue::String(String::from(&xmp_result.ok()?)))
     }
 
     pub fn set_metadata(&mut self, meta: Np, value: &PropertyValue) -> bool {
         if let Some(ix) = property_index_to_xmp(meta) {
             match *value {
                 PropertyValue::Empty => {
-                    return self.xmp.xmp.delete_property(&ix.ns, &ix.property).is_ok()
+                    return self
+                        .xmp_meta
+                        .xmp
+                        .delete_property(&ix.ns, &ix.property)
+                        .is_ok()
                 }
                 PropertyValue::Int(i) => {
                     return self
+                        .xmp_meta
                         .xmp
-                        .xmp
-                        .set_property_i32(&ix.ns, &ix.property, i, exempi::PropFlags::NONE)
+                        .set_property_i32(&ix.ns, &ix.property, i, exempi2::PropFlags::NONE)
                         .is_ok()
                 }
                 PropertyValue::String(ref s) => {
                     if s.is_empty() {
-                        return self.xmp.xmp.delete_property(&ix.ns, &ix.property).is_ok();
-                    } else if self
-                        .xmp
-                        .xmp
-                        .set_property(&ix.ns, &ix.property, s, exempi::PropFlags::NONE)
-                        .is_err()
-                    {
-                        if exempi::get_error() == exempi::Error::BadXPath {
+                        return self
+                            .xmp_meta
+                            .xmp
+                            .delete_property(&ix.ns, &ix.property)
+                            .is_ok();
+                    } else if let Err(err) = self.xmp_meta.xmp.set_property(
+                        &ix.ns,
+                        &ix.property,
+                        s,
+                        exempi2::PropFlags::NONE,
+                    ) {
+                        if err == exempi2::Error(exempi2::XmpError::BadXPath) {
                             return self
-                                .xmp
+                                .xmp_meta
                                 .xmp
                                 .set_localized_text(
                                     &ix.ns,
@@ -132,7 +145,7 @@ impl LibMetadata {
                                     "",
                                     "x-default",
                                     s,
-                                    exempi::PropFlags::NONE,
+                                    exempi2::PropFlags::NONE,
                                 )
                                 .is_ok();
                         }
@@ -141,20 +154,25 @@ impl LibMetadata {
                     }
                 }
                 PropertyValue::StringArray(ref sa) => {
-                    if self.xmp.xmp.delete_property(&ix.ns, &ix.property).is_err() {
+                    if self
+                        .xmp_meta
+                        .xmp
+                        .delete_property(&ix.ns, &ix.property)
+                        .is_err()
+                    {
                         err_out!("Error deleting property {}", &ix.property);
                         return false;
                     }
                     for s in sa {
                         if self
-                            .xmp
+                            .xmp_meta
                             .xmp
                             .append_array_item(
                                 &ix.ns,
                                 &ix.property,
-                                exempi::PropFlags::VALUE_IS_ARRAY,
+                                exempi2::PropFlags::VALUE_IS_ARRAY,
                                 s,
-                                exempi::PropFlags::NONE,
+                                exempi2::PropFlags::NONE,
                             )
                             .is_err()
                         {
@@ -167,18 +185,18 @@ impl LibMetadata {
                 PropertyValue::Date(ref d) => {
                     let xmp_date = xmp_date_from(d);
                     return self
+                        .xmp_meta
                         .xmp
-                        .xmp
-                        .set_property_date(&ix.ns, &ix.property, &xmp_date, exempi::PropFlags::NONE)
+                        .set_property_date(
+                            &ix.ns,
+                            &ix.property,
+                            &xmp_date,
+                            exempi2::PropFlags::NONE,
+                        )
                         .is_ok();
                 }
             }
-            err_out!(
-                "error setting property {}:{} {}",
-                ix.ns,
-                ix.property,
-                exempi::get_error() as u32
-            );
+            err_out!("error setting property {}:{}", ix.ns, ix.property);
             return false;
         }
         err_out!("Unknown property {:?}", meta);
@@ -191,39 +209,35 @@ impl LibMetadata {
         for prop_id in propset {
             match *prop_id {
                 Np::Index(NpXmpRatingProp) => {
-                    if let Some(rating) = self.xmp.rating() {
+                    if let Some(rating) = self.xmp_meta.rating() {
                         props.set_value(*prop_id, PropertyValue::Int(rating));
                     }
                 }
                 Np::Index(NpXmpLabelProp) => {
-                    if let Some(label) = self.xmp.label() {
+                    if let Some(label) = self.xmp_meta.label() {
                         props.set_value(*prop_id, PropertyValue::String(label));
                     }
                 }
                 Np::Index(NpTiffOrientationProp) => {
-                    if let Some(orientation) = self.xmp.orientation() {
+                    if let Some(orientation) = self.xmp_meta.orientation() {
                         props.set_value(*prop_id, PropertyValue::Int(orientation));
                     }
                 }
                 Np::Index(NpExifDateTimeOriginalProp) => {
-                    if let Some(date) = self.xmp.creation_date() {
+                    if let Some(date) = self.xmp_meta.creation_date() {
                         props.set_value(*prop_id, PropertyValue::Date(date));
                     }
                 }
                 Np::Index(NpIptcKeywordsProp) => {
-                    let mut iter = exempi::XmpIterator::new(
-                        &self.xmp.xmp,
+                    let mut iter = exempi2::XmpIterator::new(
+                        &self.xmp_meta.xmp,
                         NS_DC,
                         "subject",
-                        exempi::IterFlags::JUST_LEAF_NODES,
+                        exempi2::IterFlags::JUST_LEAF_NODES,
                     );
                     let mut keywords: Vec<String> = vec![];
-                    let mut schema = exempi::XmpString::new();
-                    let mut name = exempi::XmpString::new();
-                    let mut value = exempi::XmpString::new();
-                    let mut flags = exempi::PropFlags::default();
-                    while iter.next(&mut schema, &mut name, &mut value, &mut flags) {
-                        keywords.push(String::from(value.to_str()));
+                    while let Some(v) = iter.next() {
+                        keywords.push(String::from(&v.value));
                     }
                     props.set_value(*prop_id, PropertyValue::StringArray(keywords));
                 }
@@ -255,9 +269,9 @@ impl LibMetadata {
 
     pub fn touch(&mut self) -> bool {
         let xmpdate = xmp_date_from(&Utc::now());
-        self.xmp
+        self.xmp_meta
             .xmp
-            .set_property_date(NS_XAP, "MetadataDate", &xmpdate, exempi::PropFlags::NONE)
+            .set_property_date(NS_XAP, "MetadataDate", &xmpdate, exempi2::PropFlags::NONE)
             .is_ok()
     }
 }
diff --git a/crates/npc-engine/src/db/library.rs b/crates/npc-engine/src/db/library.rs
index 48aaa0b..9193144 100644
--- a/crates/npc-engine/src/db/library.rs
+++ b/crates/npc-engine/src/db/library.rs
@@ -1343,8 +1343,6 @@ mod test {
     fn file_bundle_import() {
         use npc_fwk::utils::exempi::XmpMeta;
 
-        exempi::init();
-
         let lib = Library::new_in_memory();
 
         assert!(lib.is_ok());
@@ -1378,7 +1376,7 @@ mod test {
         // of the XMP SDK is written in the header so we can do comparisons
         // byte by byte
         let original_xmp_packet =
-            exempi::Xmp::from_buffer(XMP_PACKET.as_bytes()).expect("XMP packet created");
+            exempi2::Xmp::from_buffer(XMP_PACKET.as_bytes()).expect("XMP packet created");
         let original_xmp_packet = XmpMeta::new_with_xmp(original_xmp_packet);
         let result = lib.set_image_properties(bundle_id, &props);
         result.expect("Setting the XMP works");
diff --git a/crates/npc-fwk/Cargo.toml b/crates/npc-fwk/Cargo.toml
index 96c2eac..34003f1 100644
--- a/crates/npc-fwk/Cargo.toml
+++ b/crates/npc-fwk/Cargo.toml
@@ -11,7 +11,7 @@ build = "build.rs"
 async-channel = "1.6.1"
 cairo-rs = "*"
 chrono = "0.4.0"
-exempi = { version = "2.6.0", git = "https://github.com/hfiguiere/exempi-rs.git";, rev="99e8ba5" }
+exempi2 = { version = "0.1.1" }
 gio-sys = "*"
 gio = "^0.14.0"
 glib-sys = "*"
diff --git a/crates/npc-fwk/src/base/date.rs b/crates/npc-fwk/src/base/date.rs
index bf400da..7e07f7c 100644
--- a/crates/npc-fwk/src/base/date.rs
+++ b/crates/npc-fwk/src/base/date.rs
@@ -1,7 +1,7 @@
 /*
  * niepce - fwk/base/date.rs
  *
- * Copyright (C) 2017-2020 Hubert Figuière
+ * Copyright (C) 2017-2021 Hubert Figuière
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,11 +24,11 @@ use chrono::{Datelike, Timelike};
 pub type Time = i64;
 pub type Date = chrono::DateTime<chrono::Utc>;
 
-pub fn xmp_date_from(d: &chrono::DateTime<chrono::Utc>) -> exempi::DateTime {
-    let mut xmp_date = exempi::DateTime::new();
+pub fn xmp_date_from(d: &chrono::DateTime<chrono::Utc>) -> exempi2::DateTime {
+    let mut xmp_date = exempi2::DateTime::new();
     xmp_date.set_date(d.year(), d.month() as i32, d.day() as i32);
     xmp_date.set_time(d.hour() as i32, d.minute() as i32, d.second() as i32);
-    xmp_date.set_timezone(exempi::XmpTzSign::UTC, 0, 0);
+    xmp_date.set_timezone(exempi2::TzSign::UTC, 0, 0);
 
     xmp_date
 }
diff --git a/crates/npc-fwk/src/lib.rs b/crates/npc-fwk/src/lib.rs
index f6674c8..2f4d649 100644
--- a/crates/npc-fwk/src/lib.rs
+++ b/crates/npc-fwk/src/lib.rs
@@ -18,7 +18,7 @@
  */
 
 extern crate chrono;
-extern crate exempi;
+extern crate exempi2;
 extern crate gdk;
 extern crate gdk_pixbuf;
 extern crate gdk_pixbuf_sys;
diff --git a/crates/npc-fwk/src/utils/exempi.rs b/crates/npc-fwk/src/utils/exempi.rs
index f20ad65..1a555f3 100644
--- a/crates/npc-fwk/src/utils/exempi.rs
+++ b/crates/npc-fwk/src/utils/exempi.rs
@@ -24,7 +24,7 @@ use std::io::prelude::*;
 use std::path::Path;
 
 use chrono::{DateTime, Utc};
-use exempi::Xmp;
+use exempi2::Xmp;
 
 use super::exiv2;
 
@@ -87,37 +87,37 @@ impl Flash {
         xmp: &mut Xmp,
         ns: &str,
         property: &str,
-    ) -> exempi::Result<()> {
+    ) -> exempi2::Result<()> {
         // XXX use set_struct_field() as soon as it is available
         xmp.set_property(
             ns,
             &format!("{}/exif:Fired", property),
             bool_to_propstring(self.fired),
-            exempi::PropFlags::NONE,
+            exempi2::PropFlags::NONE,
         )?;
         xmp.set_property(
             ns,
             &format!("{}/exif:Return", property),
             &format!("{}", self.rturn),
-            exempi::PropFlags::NONE,
+            exempi2::PropFlags::NONE,
         )?;
         xmp.set_property(
             ns,
             &format!("{}/exif:Mode", property),
             &format!("{}", self.mode),
-            exempi::PropFlags::NONE,
+            exempi2::PropFlags::NONE,
         )?;
         xmp.set_property(
             ns,
             &format!("{}/exif:Function", property),
             bool_to_propstring(self.function),
-            exempi::PropFlags::NONE,
+            exempi2::PropFlags::NONE,
         )?;
         xmp.set_property(
             ns,
             &format!("{}/exif:RedEyeMode", property),
             bool_to_propstring(self.red_eye),
-            exempi::PropFlags::NONE,
+            exempi2::PropFlags::NONE,
         )?;
 
         Ok(())
@@ -133,14 +133,13 @@ pub struct ExempiManager {}
 
 impl ExempiManager {
     pub fn new(namespaces: Option<Vec<NsDef>>) -> ExempiManager {
-        if exempi::init() {
-            exempi::register_namespace(NIEPCE_XMP_NAMESPACE, NIEPCE_XMP_NS_PREFIX);
-            exempi::register_namespace(UFRAW_INTEROP_NAMESPACE, UFRAW_INTEROP_NS_PREFIX);
-        }
+        exempi2::register_namespace(NIEPCE_XMP_NAMESPACE, NIEPCE_XMP_NS_PREFIX);
+        exempi2::register_namespace(UFRAW_INTEROP_NAMESPACE, UFRAW_INTEROP_NS_PREFIX);
+
         if let Some(nslist) = namespaces {
             for nsdef in nslist {
                 // TOOD check the return value
-                exempi::register_namespace(nsdef.ns.as_str(), nsdef.prefix.as_str());
+                exempi2::register_namespace(nsdef.ns.as_str(), nsdef.prefix.as_str());
             }
         }
         ExempiManager {}
@@ -163,13 +162,13 @@ impl Default for XmpMeta {
 impl XmpMeta {
     pub fn new() -> XmpMeta {
         XmpMeta {
-            xmp: exempi::Xmp::new(),
+            xmp: exempi2::Xmp::new(),
             keywords: Vec::new(),
             keywords_fetched: false,
         }
     }
 
-    pub fn new_with_xmp(xmp: exempi::Xmp) -> XmpMeta {
+    pub fn new_with_xmp(xmp: exempi2::Xmp) -> XmpMeta {
         XmpMeta {
             xmp,
             keywords: Vec::new(),
@@ -183,14 +182,12 @@ impl XmpMeta {
     {
         let file: &Path = p.as_ref();
         if !file.exists() {
-            err_out!("File {:?} doesn't exist", &file);
+            // XXX return an error.
             return None;
         }
         let mut meta: Option<XmpMeta> = None;
         if !sidecar_only {
-            if let Ok(xmpfile) =
-                exempi::XmpFile::open_new(&*file.to_string_lossy(), exempi::OpenFlags::READ)
-            {
+            if let Ok(xmpfile) = exempi2::XmpFile::new_from_file(file, exempi2::OpenFlags::READ) {
                 meta = match xmpfile.get_new_xmp() {
                     Ok(xmp) => Some(Self::new_with_xmp(xmp)),
                     _ => exiv2::xmp_from_exiv2(file),
@@ -204,7 +201,7 @@ impl XmpMeta {
         if let Ok(mut sidecarfile) = sidecaropen {
             let mut sidecarcontent = String::new();
             if sidecarfile.read_to_string(&mut sidecarcontent).is_ok() {
-                let mut xmp = exempi::Xmp::new();
+                let mut xmp = exempi2::Xmp::new();
                 if xmp.parse(sidecarcontent.into_bytes().as_slice()).is_ok() {
                     sidecar_meta = Some(Self::new_with_xmp(xmp));
                 }
@@ -255,36 +252,28 @@ impl XmpMeta {
         }
 
         // Properties in source but not in destination gets copied over.
-        let mut iter = exempi::XmpIterator::new(&self.xmp, "", "", exempi::IterFlags::PROPERTIES);
-        {
-            use exempi::XmpString;
-            let mut schema = XmpString::new();
-            let mut name = XmpString::new();
-            let mut value = XmpString::new();
-            let mut option = exempi::PropFlags::default();
-            while iter.next(&mut schema, &mut name, &mut value, &mut option) {
-                if name.to_str().is_empty() {
-                    continue;
-                }
-                if option.contains(exempi::PropFlags::VALUE_IS_ARRAY)
-                    || option.contains(exempi::PropFlags::VALUE_IS_STRUCT)
-                {
-                    iter.skip(exempi::IterSkipFlags::SUBTREE);
-                    continue;
-                }
+        let mut iter = exempi2::XmpIterator::new(&self.xmp, "", "", exempi2::IterFlags::PROPERTIES);
+        while let Some(v) = iter.next() {
+            if v.name.is_empty() {
+                continue;
+            }
+            if v.option.contains(exempi2::PropFlags::VALUE_IS_ARRAY)
+                || v.option.contains(exempi2::PropFlags::VALUE_IS_STRUCT)
+            {
+                exempi2::XmpIterator::skip(&mut iter, exempi2::IterSkipFlags::SUBTREE);
+                continue;
+            }
 
-                if !dest.xmp.has_property(schema.to_str(), name.to_str())
-                    && dest
-                        .xmp
-                        .set_property(
-                            schema.to_str(),
-                            name.to_str(),
-                            value.to_str(),
-                            exempi::PropFlags::NONE,
-                        )
-                        .is_err()
+            let schema = v.schema.to_str().unwrap_or("");
+            let name = v.name.to_str().unwrap_or("");
+            if !dest.xmp.has_property(schema, name) {
+                let value = v.value.to_str().unwrap_or("");
+                if dest
+                    .xmp
+                    .set_property(schema, name, value, exempi2::PropFlags::NONE)
+                    .is_err()
                 {
-                    err_out!("Can set property {}", name);
+                    err_out!("Can not set property {}", v.name);
                 }
             }
         }
@@ -294,13 +283,13 @@ impl XmpMeta {
 
     pub fn serialize_inline(&self) -> String {
         if let Ok(xmpstr) = self.xmp.serialize_and_format(
-            exempi::SerialFlags::OMITPACKETWRAPPER | exempi::SerialFlags::OMITALLFORMATTING,
+            exempi2::SerialFlags::OMITPACKETWRAPPER | exempi2::SerialFlags::OMITALLFORMATTING,
             0,
             "",
             "",
             0,
         ) {
-            let buf = String::from(xmpstr.to_str());
+            let buf = String::from(&xmpstr);
             return buf;
         }
         String::new()
@@ -309,9 +298,9 @@ impl XmpMeta {
     pub fn serialize(&self) -> String {
         if let Ok(xmpstr) =
             self.xmp
-                .serialize_and_format(exempi::SerialFlags::OMITPACKETWRAPPER, 0, "\n", "", 0)
+                .serialize_and_format(exempi2::SerialFlags::OMITPACKETWRAPPER, 0, "\n", "", 0)
         {
-            let buf = String::from(xmpstr.to_str());
+            let buf = String::from(&xmpstr);
             return buf;
         }
         String::new()
@@ -322,61 +311,63 @@ impl XmpMeta {
     }
 
     pub fn orientation(&self) -> Option<i32> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::default();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
         self.xmp
             .get_property_i32(NS_TIFF, "Orientation", &mut flags)
             .ok()
     }
 
     pub fn label(&self) -> Option<String> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::default();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
         let xmpstring = self.xmp.get_property(NS_XAP, "Label", &mut flags).ok()?;
-        Some(String::from(xmpstring.to_str()))
+        Some(String::from(&xmpstring))
     }
 
     pub fn rating(&self) -> Option<i32> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::default();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
         self.xmp.get_property_i32(NS_XAP, "Rating", &mut flags).ok()
     }
 
     pub fn flag(&self) -> Option<i32> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::empty();
         self.xmp
             .get_property_i32(NIEPCE_XMP_NAMESPACE, "Flag", &mut flags)
             .ok()
     }
 
     pub fn creation_date(&self) -> Option<DateTime<Utc>> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::default();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
         let xmpstring = self
             .xmp
             .get_property(NS_EXIF, "DateTimeOriginal", &mut flags)
             .ok()?;
-        let date = DateTime::parse_from_rfc3339(xmpstring.to_str()).ok()?;
+        let date = xmpstring
+            .to_str()
+            .and_then(|s| DateTime::parse_from_rfc3339(s).ok())?;
 
         Some(date.with_timezone(&Utc))
     }
 
     pub fn creation_date_str(&self) -> Option<String> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::empty();
         let xmpstring = self
             .xmp
             .get_property(NS_EXIF, "DateTimeOriginal", &mut flags)
             .ok()?;
-        Some(String::from(xmpstring.to_str()))
+        Some(String::from(&xmpstring))
     }
 
     /// Get the date property and return a Option<DateTime<Utc>> parsed
     /// from the string value.
     pub fn get_date_property(&self, ns: &str, property: &str) -> Option<DateTime<Utc>> {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::default();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
         let property = self.xmp.get_property(ns, property, &mut flags);
         if property.is_err() {
             err_out!("Error getting date property {:?}", property.err());
             return None;
         }
-        let xmpstring = property.unwrap();
-        let parsed = DateTime::parse_from_rfc3339(xmpstring.to_str());
+        let xmpstring = property.as_ref().ok().and_then(|s| s.to_str()).unwrap();
+        let parsed = DateTime::parse_from_rfc3339(xmpstring);
         if parsed.is_err() {
             err_out!(
                 "Error parsing property value '{}': {:?}",
@@ -391,20 +382,14 @@ impl XmpMeta {
 
     pub fn keywords(&mut self) -> &Vec<String> {
         if !self.keywords_fetched {
-            use exempi::XmpString;
-
-            let mut iter = exempi::XmpIterator::new(
+            let mut iter = exempi2::XmpIterator::new(
                 &self.xmp,
                 NS_DC,
                 "subject",
-                exempi::IterFlags::JUST_LEAF_NODES,
+                exempi2::IterFlags::JUST_LEAF_NODES,
             );
-            let mut schema = XmpString::new();
-            let mut name = XmpString::new();
-            let mut value = XmpString::new();
-            let mut option = exempi::PropFlags::default();
-            while iter.next(&mut schema, &mut name, &mut value, &mut option) {
-                self.keywords.push(String::from(value.to_str()));
+            while let Some(v) = iter.next() {
+                self.keywords.push(String::from(&v.value));
             }
             self.keywords_fetched = true;
         }
@@ -469,7 +454,7 @@ pub fn gps_coord_from_xmp(xmps: &str) -> Option<f64> {
 
 /// Get and XMP date from an Exif date string
 /// XXX Currently assume it is UTC.
-pub fn xmp_date_from_exif(d: &str) -> Option<exempi::DateTime> {
+pub fn xmp_date_from_exif(d: &str) -> Option<exempi2::DateTime> {
     let v: Vec<&str> = d.split(' ').collect();
     if v.len() != 2 {
         err_out!("Space split failed {:?}", v);
@@ -508,12 +493,12 @@ pub fn xmp_date_from_exif(d: &str) -> Option<exempi::DateTime> {
         return None;
     }
 
-    let mut xmp_date = exempi::DateTime::new();
+    let mut xmp_date = exempi2::DateTime::new();
 
     xmp_date.set_date(year, month, day);
     xmp_date.set_time(hour, min, sec);
     // XXX use an actual timezone
-    xmp_date.set_timezone(exempi::XmpTzSign::UTC, 0, 0);
+    xmp_date.set_timezone(exempi2::TzSign::UTC, 0, 0);
 
     Some(xmp_date)
 }
@@ -537,7 +522,7 @@ mod tests {
     use super::xmp_date_from_exif;
     use super::ExempiManager;
     use super::XmpMeta;
-    use exempi;
+    use exempi2;
     use std::path::PathBuf;
 
     fn get_xmp_sample_path() -> PathBuf {
@@ -580,10 +565,10 @@ mod tests {
     }
 
     fn test_property_value(meta: &XmpMeta, ns: &str, property: &str, expected_value: &str) {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::empty();
         let value = meta.xmp.get_property(ns, property, &mut flags);
         assert!(value.is_ok());
-        assert_eq!(value.unwrap().to_str(), expected_value);
+        assert_eq!(value.unwrap().to_str(), Some(expected_value));
     }
 
     fn test_property_array_value(
@@ -593,10 +578,10 @@ mod tests {
         idx: i32,
         expected_value: &str,
     ) {
-        let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+        let mut flags: exempi2::PropFlags = exempi2::PropFlags::empty();
         let value = meta.xmp.get_array_item(ns, property, idx, &mut flags);
         assert!(value.is_ok());
-        assert_eq!(value.unwrap().to_str(), expected_value);
+        assert_eq!(value.unwrap().to_str(), Some(expected_value));
     }
 
     #[test]
diff --git a/crates/npc-fwk/src/utils/exiv2.rs b/crates/npc-fwk/src/utils/exiv2.rs
index c2c8afa..8b4bcd9 100644
--- a/crates/npc-fwk/src/utils/exiv2.rs
+++ b/crates/npc-fwk/src/utils/exiv2.rs
@@ -1,7 +1,7 @@
 /*
  * niepce - fwk/utils/exiv2.rs
  *
- * Copyright (C) 2018-2020 Hubert Figuière
+ * Copyright (C) 2018-2021 Hubert Figuière
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ enum Converted {
     /// An int 32
     Int(i32),
     /// an Xmp DateTime value
-    Date(Option<exempi::DateTime>),
+    Date(Option<exempi2::DateTime>),
     /// The Flash XMP structure
     Flash(Flash),
 }
@@ -278,14 +278,14 @@ fn ascii_tag_to_xmp(
     meta: &rexiv2::Metadata,
     tag: &str,
     xmp_prop: &XmpPropDesc,
-    xmp: &mut exempi::Xmp,
+    xmp: &mut exempi2::Xmp,
 ) {
     if let Ok(value) = meta.get_tag_string(tag) {
         let converted = convert(xmp_prop.2, &value);
         match converted {
             Converted::Str(s) => {
                 if let Err(err) =
-                    xmp.set_property(xmp_prop.0, xmp_prop.1, &s, exempi::PropFlags::NONE)
+                    xmp.set_property(xmp_prop.0, xmp_prop.1, &s, exempi2::PropFlags::NONE)
                 {
                     err_out!(
                         "Error setting property {} {}: {:?}",
@@ -298,7 +298,7 @@ fn ascii_tag_to_xmp(
             Converted::Date(d) => {
                 if let Some(d) = d {
                     if let Err(err) =
-                        xmp.set_property_date(xmp_prop.0, xmp_prop.1, &d, exempi::PropFlags::NONE)
+                        xmp.set_property_date(xmp_prop.0, xmp_prop.1, &d, exempi2::PropFlags::NONE)
                     {
                         err_out!(
                             "Error setting property {} {}: {:?}",
@@ -324,7 +324,7 @@ fn int_tag_to_xmp(
     tag: &str,
     tagtype: rexiv2::TagType,
     xmp_prop: &XmpPropDesc,
-    xmp: &mut exempi::Xmp,
+    xmp: &mut exempi2::Xmp,
 ) {
     // XXX rexiv2 returns an i32, which is a problem for UnsignedLong
     match xmp_prop.2 {
@@ -343,7 +343,7 @@ fn int_tag_to_xmp(
         Conversion::None => {
             let value = meta.get_tag_numeric(&tag);
             if let Err(err) =
-                xmp.set_property_i32(xmp_prop.0, xmp_prop.1, value, exempi::PropFlags::NONE)
+                xmp.set_property_i32(xmp_prop.0, xmp_prop.1, value, exempi2::PropFlags::NONE)
             {
                 err_out!(
                     "Error setting property {} {}: {:?}",
@@ -356,7 +356,7 @@ fn int_tag_to_xmp(
         Conversion::Interpreted => {
             if let Ok(value) = meta.get_tag_interpreted_string(&tag) {
                 if let Err(err) =
-                    xmp.set_property(xmp_prop.0, xmp_prop.1, &value, exempi::PropFlags::NONE)
+                    xmp.set_property(xmp_prop.0, xmp_prop.1, &value, exempi2::PropFlags::NONE)
                 {
                     err_out!(
                         "Error setting property {} {}: {:?}",
@@ -371,7 +371,7 @@ fn int_tag_to_xmp(
             err_out!("Unknown conversion from {:?} to {:?}", tagtype, xmp_prop.2);
             let value = meta.get_tag_numeric(&tag);
             if let Err(err) =
-                xmp.set_property_i32(xmp_prop.0, xmp_prop.1, value, exempi::PropFlags::NONE)
+                xmp.set_property_i32(xmp_prop.0, xmp_prop.1, value, exempi2::PropFlags::NONE)
             {
                 err_out!(
                     "Error setting property {} {}: {:?}",
@@ -386,7 +386,7 @@ fn int_tag_to_xmp(
 
 pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
     if let Ok(meta) = rexiv2::Metadata::new_from_path(file) {
-        let mut xmp = exempi::Xmp::new();
+        let mut xmp = exempi2::Xmp::new();
         let mut all_tags: Vec<String> = vec![];
         if let Ok(mut tags) = meta.get_exif_tags() {
             all_tags.append(&mut tags);
@@ -425,7 +425,7 @@ pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
                                         xmp_prop.0,
                                         xmp_prop.1,
                                         &value,
-                                        exempi::PropFlags::NONE,
+                                        exempi2::PropFlags::NONE,
                                     ) {
                                         err_out!(
                                             "Error setting property {} {}: {:?}",
@@ -443,7 +443,7 @@ pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
                                         xmp_prop.0,
                                         xmp_prop.1,
                                         &value_str,
-                                        exempi::PropFlags::NONE,
+                                        exempi2::PropFlags::NONE,
                                     ) {
                                         err_out!(
                                             "Error setting property {} {}: {:?}",
@@ -461,7 +461,7 @@ pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
                                     xmp_prop.0,
                                     xmp_prop.1,
                                     &value,
-                                    exempi::PropFlags::NONE,
+                                    exempi2::PropFlags::NONE,
                                 ) {
                                     err_out!(
                                         "Error setting property {} {}: {:?}",
@@ -479,7 +479,7 @@ pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
                                         xmp_prop.0,
                                         xmp_prop.1,
                                         &value,
-                                        exempi::PropFlags::NONE,
+                                        exempi2::PropFlags::NONE,
                                     ) {
                                         err_out!(
                                             "Error setting property {} {}: {:?}",
@@ -503,10 +503,10 @@ pub fn xmp_from_exiv2<S: AsRef<OsStr>>(file: S) -> Option<XmpMeta> {
         }
         meta.get_gps_info();
 
-        let mut options = exempi::PropFlags::default();
+        let mut options = exempi2::PropFlags::default();
         if let Ok(date) = xmp.get_property_date(NS_XAP, "ModifyDate", &mut options) {
             if let Err(err) =
-                xmp.set_property_date(NS_XAP, "MetadataDate", &date, exempi::PropFlags::NONE)
+                xmp.set_property_date(NS_XAP, "MetadataDate", &date, exempi2::PropFlags::NONE)
             {
                 err_out!("Error setting MetadataDate: {:?}", &err);
             }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]