Expand description
A circular buffer for strings and traits for in-place string transforms.
This crate provides two key types: the CharCircle
struct and the
StringTransform
trait. The CharCircle
is a circular buffer
specialized for UTF-8 strings, and the StringTransform
trait builds upon
it to provide a character-oriented API for in-place string transformations.
In short, StringTransform
allows you to implement transformations as
iterator adaptors, with copy-on-write optimizations in mind.
The CharCircle
uses internal mutability. This enables its contents to be
consumed by an external iterator, Chars
. As a consequence, the
CharCircle
is not Sync
. It is implemented as a RefCell
around the
RawCircle
, which has a nearly identical API, uses external mutability,
is thread-safe, and does not provide a consuming iterator.
The StringTransform
trait is implemented by factories of iterator
adaptors. For simple cases, the SimpleTransform
trait provides an
alternative that is implemented directly by the adaptor.
§Example: To Uppercase
Transforms which don’t require configuration are most easily implemented
with SimpleTransform
.
Here we implement an uppercase transform:
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?");
§Example: Caesar Cipher
Transforms that need to be configured should define a factory which
implements StringTransform
.
Here we implement a Caesar cipher configured with its key:
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");
Structs§
- Char
Circle - A circular buffer of characters.
- Chars
- An iterator that consumes characters in a
CharCircle
. - RawCircle
- A thread-safe version of
CharCircle
. - Simple
String Transform - Used when you have a
SimpleTransform
but need aStringTransform
.
Traits§
- Simple
Transform - A simple trait for in-place string transformations.
- String
Transform - A factory trait for in-place string transformations.