[niepce/lr-import: 18/20] npc-fwk: improve exempi support
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce/lr-import: 18/20] npc-fwk: improve exempi support
- Date: Mon, 20 Dec 2021 05:37:15 +0000 (UTC)
commit 6d9e1839c7abf6c7d9dffcb3ede5e917691e40e2
Author: Hubert Figuière <hub figuiere net>
Date: Tue Dec 14 22:58:19 2021 -0500
npc-fwk: improve exempi support
- Add more test
- Fix datetime support to use fixed offset timezone
- Update to exempi2 0.1.2
Cargo.lock | 102 ++++++++++++++++----------------
crates/npc-engine/Cargo.toml | 2 +-
crates/npc-engine/src/db/libmetadata.rs | 74 +++++++++++++++++++++--
crates/npc-fwk/Cargo.toml | 2 +-
crates/npc-fwk/src/base/date.rs | 41 ++++++++++++-
crates/npc-fwk/src/utils/exempi.rs | 29 ++++-----
6 files changed, 172 insertions(+), 78 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 6576eb4..92c6c9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -24,18 +24,18 @@ dependencies = [
[[package]]
name = "ansi_term"
-version = "0.11.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
-version = "1.0.45"
+version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7"
+checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]]
name = "async-channel"
@@ -186,9 +186,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "2.33.3"
+version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
@@ -222,9 +222,9 @@ checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
[[package]]
name = "exempi-sys"
-version = "2.5.0"
+version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "092ed317836115f2a074e1fcc8ed9b2ced33bc7af1e71512cd4aa3a5be696e37"
+checksum = "feb66d7287eca6ff9fcdfcf8da289fd72c398693afff64f608d041431d24fc4f"
dependencies = [
"libc",
"pkg-config",
@@ -232,9 +232,9 @@ dependencies = [
[[package]]
name = "exempi2"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1deb5527e7a45f3ac714fc6cb78fa40e2be21a39824c93280deb71877216aa7d"
+checksum = "760d769a5bf6f641cd1ba6140c10d94ce4d5fa813656ea4fb1f482177cebd1c6"
dependencies = [
"bitflags",
"exempi-sys",
@@ -265,24 +265,24 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
+checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
+checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
[[package]]
name = "futures-executor"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
+checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97"
dependencies = [
"futures-core",
"futures-task",
@@ -291,23 +291,22 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
+checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
[[package]]
name = "futures-task"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
+checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
[[package]]
name = "futures-util"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
+checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
dependencies = [
- "autocfg",
"futures-core",
"futures-task",
"pin-project-lite",
@@ -609,18 +608,18 @@ dependencies = [
[[package]]
name = "itertools"
-version = "0.10.1"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [
"either",
]
[[package]]
name = "itoa"
-version = "0.4.8"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "lazy_static"
@@ -630,9 +629,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.107"
+version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]]
name = "libopenraw-rs"
@@ -650,9 +649,9 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
-version = "0.23.1"
+version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abd5850c449b40bacb498b2bbdfaff648b1b055630073ba8db499caf2d0ea9f2"
+checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58"
dependencies = [
"pkg-config",
"vcpkg",
@@ -714,9 +713,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
-version = "0.6.4"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
@@ -956,9 +955,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.22"
+version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
+checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]]
name = "ppv-lite86"
@@ -1002,9 +1001,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.32"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
+checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a"
dependencies = [
"unicode-xid",
]
@@ -1130,9 +1129,9 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.5"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "semver"
@@ -1154,18 +1153,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.130"
+version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
+checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.130"
+version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
+checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
dependencies = [
"proc-macro2",
"quote",
@@ -1174,9 +1173,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.69"
+version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
+checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
dependencies = [
"itoa",
"ryu",
@@ -1221,9 +1220,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.81"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [
"proc-macro2",
"quote",
@@ -1299,11 +1298,12 @@ dependencies = [
[[package]]
name = "time"
-version = "0.1.43"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
+ "wasi",
"winapi",
]
@@ -1375,9 +1375,9 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "winapi"
diff --git a/crates/npc-engine/Cargo.toml b/crates/npc-engine/Cargo.toml
index a4a2041..595c957 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"
-exempi2 = { version = "0.1.1" }
+exempi2 = { version = "0.1.2" }
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 30e71aa..973b598 100644
--- a/crates/npc-engine/src/db/libmetadata.rs
+++ b/crates/npc-engine/src/db/libmetadata.rs
@@ -17,15 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-use chrono::Utc;
-
use super::libfile::FileType;
use super::props;
use super::NiepceProperties as Np;
use super::{FromDb, LibraryId};
use crate::{NiepcePropertyBag, NiepcePropertySet};
use npc_fwk::utils::exempi::{NS_DC, NS_XAP};
-use npc_fwk::{xmp_date_from, PropertyBag, PropertySet, PropertyValue, XmpMeta};
+use npc_fwk::{xmp_date_from, Date, PropertyBag, PropertySet, PropertyValue, XmpMeta};
#[derive(Clone)]
pub struct LibMetadata {
@@ -229,14 +227,14 @@ impl LibMetadata {
}
}
Np::Index(NpIptcKeywordsProp) => {
- let mut iter = exempi2::XmpIterator::new(
+ let iter = exempi2::XmpIterator::new(
&self.xmp_meta.xmp,
NS_DC,
"subject",
exempi2::IterFlags::JUST_LEAF_NODES,
);
let mut keywords: Vec<String> = vec![];
- while let Some(v) = iter.next() {
+ for v in iter {
keywords.push(String::from(&v.value));
}
props.set_value(*prop_id, PropertyValue::StringArray(keywords));
@@ -268,7 +266,8 @@ impl LibMetadata {
}
pub fn touch(&mut self) -> bool {
- let xmpdate = xmp_date_from(&Utc::now());
+ let local = chrono::Local::now();
+ let xmpdate = xmp_date_from(&Date::from(local));
self.xmp_meta
.xmp
.set_property_date(NS_XAP, "MetadataDate", &xmpdate, exempi2::PropFlags::NONE)
@@ -317,3 +316,66 @@ pub extern "C" fn engine_libmetadata_to_properties(
let result = Box::new(meta.to_properties(propset));
Box::into_raw(result)
}
+
+#[cfg(test)]
+mod test {
+
+ use super::{LibMetadata, Np};
+ use crate::NiepcePropertyIdx::*;
+ use chrono::TimeZone;
+ use npc_fwk::{PropertySet, PropertyValue, XmpMeta};
+
+ const XMP_PACKET: &[u8] = include_bytes!("../../tests/test.xmp");
+
+ #[test]
+ fn test_libmetadata() {
+ let xmp = exempi2::Xmp::from_buffer(XMP_PACKET);
+ assert!(xmp.is_ok());
+
+ let xmp = xmp.unwrap();
+ let xmp_meta = XmpMeta::new_with_xmp(xmp);
+ let libmetadata = LibMetadata::new_with_xmp(1, xmp_meta);
+ let mut propset = PropertySet::new();
+ propset.insert(Np::Index(NpIptcKeywordsProp));
+ propset.insert(Np::Index(NpTiffOrientationProp));
+ propset.insert(Np::Index(NpExifDateTimeOriginalProp));
+
+ let bag = libmetadata.to_properties(&propset);
+ assert_eq!(bag.len(), 3);
+
+ let keywords = bag.get(&Np::Index(NpIptcKeywordsProp));
+ assert!(keywords.is_some());
+
+ if let PropertyValue::StringArray(keywords) = keywords.unwrap() {
+ assert_eq!(keywords.len(), 5);
+ assert_eq!(keywords[0], "choir");
+ assert_eq!(keywords[1], "night");
+ assert_eq!(keywords[2], "ontario");
+ assert_eq!(keywords[3], "ottawa");
+ assert_eq!(keywords[4], "parliament of canada");
+ } else {
+ unreachable!();
+ }
+
+ let orientation = bag.get(&Np::Index(NpTiffOrientationProp));
+ assert!(orientation.is_some());
+
+ if let PropertyValue::Int(orientation) = orientation.unwrap() {
+ assert_eq!(orientation, &1);
+ } else {
+ unreachable!();
+ }
+
+ let creation_date = bag.get(&Np::Index(NpExifDateTimeOriginalProp));
+ assert!(creation_date.is_some());
+
+ if let PropertyValue::Date(creation_date) = creation_date.unwrap() {
+ let date = chrono::FixedOffset::west(5 * 3600)
+ .ymd(2006, 12, 07)
+ .and_hms(23, 37, 30);
+ assert_eq!(creation_date, &date);
+ } else {
+ unreachable!();
+ }
+ }
+}
diff --git a/crates/npc-fwk/Cargo.toml b/crates/npc-fwk/Cargo.toml
index 34003f1..a653e8a 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"
-exempi2 = { version = "0.1.1" }
+exempi2 = { version = "0.1.2" }
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 7e07f7c..c7d54dd 100644
--- a/crates/npc-fwk/src/base/date.rs
+++ b/crates/npc-fwk/src/base/date.rs
@@ -22,13 +22,25 @@ use std::ffi::CString;
use chrono::{Datelike, Timelike};
pub type Time = i64;
-pub type Date = chrono::DateTime<chrono::Utc>;
+pub type Date = chrono::DateTime<chrono::FixedOffset>;
+
+/// Convert an `exempi2::DateTime` to a `chrono::DateTime<FixedOffset>`
+pub fn xmp_date_from(d: &Date) -> exempi2::DateTime {
+ use exempi2::TzSign;
-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(exempi2::TzSign::UTC, 0, 0);
+ let offset = d.offset().local_minus_utc();
+ let sign = if offset == 0 {
+ TzSign::UTC
+ } else if offset > 0 {
+ TzSign::East
+ } else {
+ TzSign::West
+ };
+ let offset = offset.abs();
+ xmp_date.set_timezone(sign, offset / 3600, offset / 60);
xmp_date
}
@@ -48,3 +60,26 @@ pub extern "C" fn fwk_date_to_string(date: &Date) -> *mut libc::c_char {
.unwrap()
.into_raw()
}
+
+#[cfg(test)]
+mod test {
+ use chrono::TimeZone;
+
+ use super::xmp_date_from;
+
+ #[test]
+ fn test_xmp_date_from() {
+ let date = chrono::FixedOffset::west(5 * 3600)
+ .ymd(2021, 12, 25)
+ .and_hms(10, 42, 12);
+ let xmp_date = xmp_date_from(&date);
+ assert_eq!(xmp_date.year(), 2021);
+ assert_eq!(xmp_date.month(), 12);
+ assert_eq!(xmp_date.day(), 25);
+
+ assert_eq!(xmp_date.hour(), 10);
+
+ assert_eq!(xmp_date.tz_hours(), 5);
+ assert_eq!(xmp_date.tz_sign(), exempi2::TzSign::West);
+ }
+}
diff --git a/crates/npc-fwk/src/utils/exempi.rs b/crates/npc-fwk/src/utils/exempi.rs
index 3ac5e91..52b8f65 100644
--- a/crates/npc-fwk/src/utils/exempi.rs
+++ b/crates/npc-fwk/src/utils/exempi.rs
@@ -23,10 +23,11 @@ use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
-use chrono::{DateTime, Utc};
+use chrono::DateTime;
use exempi2::Xmp;
use super::exiv2;
+use crate::Date;
pub const NIEPCE_XMP_NAMESPACE: &str = "http://xmlns.figuiere.net/ns/niepce/1.0";
pub const NIEPCE_XMP_NS_PREFIX: &str = "niepce";
@@ -343,7 +344,7 @@ impl XmpMeta {
.ok()
}
- pub fn creation_date(&self) -> Option<DateTime<Utc>> {
+ pub fn creation_date(&self) -> Option<Date> {
let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
let xmpstring = self
.xmp
@@ -353,7 +354,7 @@ impl XmpMeta {
.to_str()
.and_then(|s| DateTime::parse_from_rfc3339(s).ok())?;
- Some(date.with_timezone(&Utc))
+ Some(date)
}
pub fn creation_date_str(&self) -> Option<String> {
@@ -367,7 +368,7 @@ impl XmpMeta {
/// 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>> {
+ pub fn get_date_property(&self, ns: &str, property: &str) -> Option<Date> {
let mut flags: exempi2::PropFlags = exempi2::PropFlags::default();
let property = self.xmp.get_property(ns, property, &mut flags);
if property.is_err() {
@@ -375,28 +376,24 @@ impl XmpMeta {
return None;
}
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 '{}': {:?}",
- xmpstring,
- parsed.err()
- );
- return None;
+ match DateTime::parse_from_rfc3339(xmpstring) {
+ Ok(parsed) => Some(parsed),
+ Err(err) => {
+ err_out!("Error parsing property value '{}': {:?}", xmpstring, err);
+ None
+ }
}
- let date = parsed.unwrap();
- Some(date.with_timezone(&Utc))
}
pub fn keywords(&mut self) -> &Vec<String> {
if !self.keywords_fetched {
- let mut iter = exempi2::XmpIterator::new(
+ let iter = exempi2::XmpIterator::new(
&self.xmp,
NS_DC,
"subject",
exempi2::IterFlags::JUST_LEAF_NODES,
);
- while let Some(v) = iter.next() {
+ for v in iter {
self.keywords.push(String::from(&v.value));
}
self.keywords_fetched = true;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]