我有一个函数可以分析从命令行参数收集的字符串。该函数检查接收到的单个参数是否与Unicode代码点符号匹配(例如U+20AC
或非BMP字符U-000020AC
的特殊情况),如果匹配,则将其转换为{{1} }。如果自变量看起来不像这种符号,则该自变量中的每个字符都将转换为char
。
该函数返回一个char
,其中包含在输入中找到的所有Unicode字符—不管如何指定它们,例如Iterator<Item = char>
,U+20AC
或U-000020AC
€
该函数可以返回三种迭代器:
在Rust中,我似乎无法从同一#![feature(trait_alias)]
use std::iter;
trait CharIterator = Iterator<Item = char>;
fn to_chars(input: &str) -> impl CharIterator {
if input.starts_with("U+") || input.starts_with("U-") {
// A Unicode codepoint reference.
let cp = &input[2..];
let c = u32::from_str_radix(cp, 16)
.ok()
.and_then(std::char::from_u32);
match c {
Some(c) => Box::new(iter::once(c)) as Box<dyn CharIterator>,
// For now, just ignore erronous input.
_ => Box::new(iter::empty::<char>()) as Box<dyn CharIterator>,
}
} else {
// Characters as-is.
Box::new(input.chars().collect::<Vec<_>>().into_iter()) as Box<dyn CharIterator>
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn to_chars_test() {
assert_eq!(vec!('a'), to_chars("a").collect::<Vec<_>>());
assert_eq!(vec!('a', 'b'), to_chars("ab").collect::<Vec<_>>());
assert_eq!(vec!('a'), to_chars("U+0061").collect::<Vec<_>>());
assert_eq!(vec!('漢', '字'), to_chars("漢字").collect::<Vec<_>>());
assert_eq!(vec!('漢'), to_chars("U+6F22").collect::<Vec<_>>());
assert_eq!(None, to_chars("U+9999999").next());
}
}
的{{1}}分支中返回不同的Iterator
实现。人们建议的解决方案是返回match
。
上面的代码有效,但这是惯用的吗?
还有更优雅的方式吗?
一些背景:我是Rust的新手,但是有Java编程经验。在Java中,最好的做法是对接口而不是实现进行编码,因此返回接口是很常见的。
我是不是通过自动尝试应用这个概念以错误的方式进入Rust编程?