3 个版本
0.1.0 | 2019年4月10日 |
---|---|
0.1.0-rc1 | 2019年4月9日 |
#219 在 解析工具
46KB
600 行
Char-circle
字符串循环缓冲区和就地字符串转换特性。
本包提供了两个关键类型:结构体 CharCircle
和特质 StringTransform
。结构体 CharCircle
是一个针对 UTF-8 字符串优化的循环缓冲区,而特质 StringTransform
则基于它提供面向字符的就地字符串转换 API。简而言之,StringTransform
允许您将转换作为迭代器适配器实现,并考虑到了写时复制的优化。
文档
用法
Char-circle 是一个纯 Rust 库。要使用它,只需将其添加到您的 Cargo.toml
[dependencies]
char-circle = "0.1.0"
lib.rs
:
字符串循环缓冲区和就地字符串转换特性。
本包提供了两个关键类型:结构体 CharCircle
和特质 StringTransform
。结构体 CharCircle
是一个针对 UTF-8 字符串优化的循环缓冲区,而特质 StringTransform
则基于它提供面向字符的就地字符串转换 API。简而言之,StringTransform
允许您将转换作为迭代器适配器实现,并考虑到了写时复制的优化。
结构体 CharCircle
使用内部可变性。这使得其内容可以被外部迭代器 Chars
消费。因此,结构体 CharCircle
不是 Sync
。它通过 RawCircle
实现,后者具有几乎相同的 API,使用外部可变性,线程安全,并且不提供消耗迭代器。
StringTransform
特质由迭代器适配器的工厂实现。对于简单的情况,SimpleTransform
特质提供了一个由适配器直接实现的替代方案。
示例:转换为大写
无需配置即可实现的转换最易使用SimpleTransform
。
在此我们实现一个大写转换
use char_circle::{SimpleTransform, Chars};
// Step 1: Define the transform as an iterator adaptor.
struct ToUpper<I>(I);
impl<I> Iterator for ToUpper<I> where I: Iterator<Item=char> {
type Item = char;
fn next(&mut self) -> Option<char> {
self.0.next().map(|ch| ch.to_ascii_uppercase())
}
}
// Step 2: Define a constructor for the adaptor with `SimpleTransform`.
impl<'a> SimpleTransform<'a> for ToUpper<Chars<'a>> {
fn transform_chars(chars: Chars<'a>) -> Self {
ToUpper(chars)
}
}
// Step 3: Profit!
let s = "can you hear me in the back?";
let s = ToUpper::transform(s);
assert_eq!(&s, "CAN YOU HEAR ME IN THE BACK?");
示例:凯撒密码
需要配置的转换应定义一个工厂,该工厂实现StringTransform
。
在此我们实现一个使用其密钥配置的凯撒密码
use char_circle::{StringTransform, Chars};
// Step 1: Define the transform as an iterator adaptor.
struct CaesarCipherIter<I> {
inner: I,
key: i32,
}
impl<I> Iterator for CaesarCipherIter<I> where I: Iterator<Item=char> {
type Item = char;
fn next(&mut self) -> Option<char> {
let plaintext = self.inner.next()?;
let ciphertext = plaintext as i32 + self.key;
let ciphertext = std::char::from_u32(ciphertext as u32).unwrap();
Some(ciphertext)
}
}
// Step 2: Define a factory for the adaptor with `StringTransform`.
struct CaesarCipher(i32);
impl<'a> StringTransform<'a> for CaesarCipher {
type Iter = CaesarCipherIter<Chars<'a>>;
fn transform_chars(&self, chars: Chars<'a>) -> Self::Iter {
CaesarCipherIter { inner: chars, key: self.0 }
}
}
// Step 3: Profit!
let encoder = CaesarCipher(8);
let decoder = CaesarCipher(-8);
let plaintext = "Veni, vidi, vici";
let ciphertext = encoder.transform(plaintext);
assert_eq!(&ciphertext, "^mvq4(~qlq4(~qkq");
let plaintext = decoder.transform(ciphertext);
assert_eq!(&plaintext, "Veni, vidi, vici");