我有一个我的应用程序支持的chrono::format::strftime
格式的静态数组。
我想避免在运行时解析它们,所以我定义了一个lazy_static!
块,将它们解析为chrono::format::Item
的集合。
然而,当我尝试迭代解析的集合时,我收到一个错误:
the trait bound `&chrono::format::StrftimeItems<'_>: std::iter::Iterator` is not satisfied
这是一个简短的复制品:
#[macro_use]
extern crate lazy_static;
extern crate chrono;
use chrono::DateTime;
use chrono::offset::FixedOffset;
use chrono::format::{Parsed, parse};
use chrono::format::strftime::StrftimeItems;
static FORMATS : &[&'static str] = &["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%S%.f"];
lazy_static! {
static ref PARSED_FORMATS : Vec<StrftimeItems<'static>> = FORMATS
.iter()
.map(|format| StrftimeItems::new(format))
.collect();
}
fn parse_datetime(s: &str) -> Option<DateTime<FixedOffset>> {
for format in PARSED_FORMATS.iter() {
let mut parsed = Parsed::new();
let dt = parse(&mut parsed, &s, format)
.and_then(|_| parsed.to_datetime() );
if dt.is_ok() {
return dt.ok()
}
}
return None
}
尝试在循环中取消引用format
会出现此错误:
error[E0507]: cannot move out of borrowed content
--> src\main.rs:21:35
|
21 | let dt = parse(&mut parsed, &s, *format)
| ^^^^^^^ cannot move out of borrowed content
error: aborting due to previous error
尝试克隆format
似乎有效,但克隆似乎多余,我想避免它。
这是正确的方法吗?或者使用宏是更好的选择?
答案 0 :(得分:1)
StrftimeItems
是一个迭代器,而不是一个可迭代的容器(如Vec
那样)。当你推进迭代器时,你不能倒回它。 parse
必须按值接收迭代器,这意味着您必须使用StrftimeItems
我们的向量(这意味着您之后无法重复使用)或克隆存储的StrftimeItems
在向量中。通过克隆StrftimeItems
,你可以产生一个新的迭代器,它的状态与原始状态不同(即前进的不会推进另一个)。
我希望避免在运行时解析它们
但是,StrftimeItems
并不能让您实现目标,因为StrftimeItems
lazily parses the format string as the iterator advances。
相反,我建议您将迭代器的结果收集到Vec<Item<'static>>
。
#[macro_use]
extern crate lazy_static;
extern crate chrono;
use chrono::DateTime;
use chrono::offset::FixedOffset;
use chrono::format::{Item, Parsed, parse};
use chrono::format::strftime::StrftimeItems;
static FORMATS : &[&'static str] = &["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%S%.f"];
lazy_static! {
static ref PARSED_FORMATS : Vec<Vec<Item<'static>>> = FORMATS
.iter()
.map(|format| StrftimeItems::new(format).collect())
.collect();
}
fn parse_datetime(s: &str) -> Option<DateTime<FixedOffset>> {
for format in PARSED_FORMATS.iter() {
let mut parsed = Parsed::new();
let dt = parse(&mut parsed, &s, format.iter().cloned())
.and_then(|_| parsed.to_datetime() );
if dt.is_ok() {
return dt.ok()
}
}
return None
}
现在,当我们致电parse
时,我们会通过format.iter().cloned()
。 format
是Vec<Item<'static>>
,iter()
生成一个新的迭代器而不是Item
的引用,而cloned()
会调整迭代器,以便每个Item
是按值返回的(通过克隆它们而不是通过引用实现)(因为parse
期望迭代器超过Item
值,而不是Item
引用。