1 个不稳定版本
0.1.0 | 2023 年 9 月 4 日 |
---|
#2063 in Rust 模式
在 bevy_aoui_widgets 中使用
62KB
1.5K SLoC
StringIter
一个过度设计的 &str 迭代器,考虑到零拷贝解析,并注重人体工程学。
lib.rs
:
一个过度设计的 &str
迭代器,考虑到零拷贝解析,并注重人体工程学。
用法
StringIter
提供了迭代和模式匹配方法,以及通常在字符串类型中找到的、对迭代器有意义的方法。
标准的 StringIter 在其 char
和 &str
表示形式中都产生一个 char,允许轻松地以它的 &str
或 Cow<str>
形式存储。
- 修剪
let mut iter = " !#$@!foo&* ".str_iter();
iter.trim();
assert_eq!(iter.as_str(), "!#$@!foo&*");
iter.trim_start_by(|x: char| !x.is_alphabetic());
assert_eq!(iter.as_str(), "foo&*");
iter.trim_end_by(|x: char| !x.is_alphabetic());
assert_eq!(iter.as_str(), "foo");
- 预览
let mut iter = "bar".str_iter();
assert_eq!(iter.peek(), Some(('b', "b")));
assert_eq!(iter.peek_back(), Some(('r', "r")));
assert_eq!(iter.peekn(2), Ok("ba"));
assert_eq!(iter.peekn_back(2), Ok("ar"));
assert_eq!(iter.peekn(4), Err("bar"));
assert_eq!(iter.peekn_back(4), Err("bar"));
- 迭代
let chars = [('😀', "😀"), ('🙁', "🙁"), ('😡', "😡"), ('😱', "😱")];
for (a, b) in "😀🙁😡😱".str_iter().zip(chars.into_iter()) {
assert_eq!(a, b);
}
- 前瞻
let mut iter = "蟹🦀a🚀𓄇ë".str_iter().look_ahead(2).strs();
assert_eq!(iter.next(), Some("蟹🦀"));
assert_eq!(iter.next(), Some("🦀a"));
assert_eq!(iter.next(), Some("a🚀"));
assert_eq!(iter.next(), Some("🚀𓄇"));
assert_eq!(iter.next(), Some("𓄇ë"));
assert_eq!(iter.next(), Some("ë"));
assert_eq!(iter.next(), None);
- 按模式切片
let mut iter = "{{foo}bar}baz".str_iter();
let mut count = 0;
let s = iter.next_slice((|x| {
match x {
'{' => count += 1,
'}' => count -= 1,
_ => (),
};
count == 0
}).sep_with(Sep::Yield));
assert_eq!(s, Some("{{foo}bar}"));
assert_eq!(iter.as_str(), "baz");
- 分割
let mut iter = "thisIsCamelCase"
.str_iter()
.into_substrs(|c: char| c.is_uppercase());
assert_eq!(iter.next(), Some("this"));
assert_eq!(iter.next(), Some("Is"));
assert_eq!(iter.next(), Some("Camel"));
assert_eq!(iter.next(), Some("Case"));
assert_eq!(iter.next(), None);
模式
我们在 trim
、slice
和 split
中使用 Patterns
。
在 trim
中,模式匹配直到找到假值。
有关处理边界情况的详细信息,请参阅 [Sep
] 和 sep_with()
。
支持的模式
匹配第 n 个 char
。
..isize
匹配前 n 个 char
。这对于 trim
很有用。
匹配一个 char。
通过向前查看匹配一个 &str
。
&[char]
或[char;N]
匹配集合中的任何字符。
char..=char
匹配范围内的字符,我们只支持包含范围以避免错误。
FnMut(char) ->FallibleBool
匹配使函数返回 true 的任何字符。
FallibleBool
可以是 bool
,Option<bool>
或 [Result<bool, E: Debug>
]
(FnMut(&str) ->FallibleBool).期望(n)
通过向前查看匹配任何 &str
,使其通过查看 n
个 char
返回 true。
(FnMut(char, &str) ->FallibleBool).期望(n)
通过向前查看匹配任何 &str
,使其通过查看 n
个 char
返回 true。
char
是 &str
中的第一个 char
。
通过间隔重复匹配。
一个将 match
模式转换为 Pattern
的宏。
- 自定义
Pattern
实现
你可以编写自己的模式类型!
示例
从一个字符串中获取 ascii 标识符
let foo = r#" [email protected] "#;
let mut iter = foo.str_iter();
iter.trim_start();
let mut quotes = 0;
let slice = match iter.peek() {
Some(('a'..='z'|'A'..='Z'|'_', _)) => {
iter.next_slice(pat!(!'a'..='z'|'A'..='Z'|'0'..='9'|'_'))
}
_ => panic!("expected ident")
};
assert_eq!(slice, Some("ferris123"));
// note @ is still in the iterator
assert_eq!(iter.as_str(), "@crab.io ");
从一个字符串中获取字符串字面量 "foo"
let foo = r#" "foo" bar "#;
let mut iter = foo.str_iter();
iter.trim_start();
let mut quotes = 0;
let slice = iter.next_slice((|c| match c {
'"' => {
quotes += 1;
quotes == 2
}
_ => false,
}).sep_with(Sep::Yield));
assert_eq!(slice, Some("\"foo\""));
assert_eq!(iter.as_str(), " bar ");
性能
此 crate 的速度与 [str::chars()
] 相当。
如果单独操作 char
,则 [str::chars()
] 更快。
但如果你需要将 char
转换回 UTF-8,则 StringIter
可能比 [str::chars()
] 更快。
安全性
这个crate使用大量不安全代码来利用UTF-8的固有特性和绕过一些边界检查和UTF-8检查。
此外,如果给定无效的UTF-8输入,我们也不能保证内存安全。
如果您发现任何稳定性问题,请提交问题。此crate中使用了恶意迭代器。
映射迭代器与StringIter
共享常规方法,在功能上是相同的。此crate中使用了恶意模式。方便地导出常用成员
use string_iter::prelude::*;