Rust · Trimming and Translating

Trimming and Translating

use stringzilla::*; 6.0.0-rc.1 · 91a27bdd

The crate provides byte-level buffer transforms, lookup-table translation, in-place replacement, and Unicode case folding / normalization.

§ Lookup Table Translation

lookup maps every byte of a source through a 256-entry table into a target, while lookup_inplace rewrites a buffer in place.

pub fn lookup<T: AsMut<[u8]>, S: AsRef<[u8]>>(target: &mut T, source: &S, table: [u8; 256]) -> Result<(), Status>;
pub fn lookup_inplace<T: AsMut<[u8]>>(buffer: &mut T, table: [u8; 256]);

lookup maps every byte through a 256-entry table; for example to lowercase ASCII:

use stringzilla as sz;

let mut to_lower: [u8; 256] = core::array::from_fn(|i| i as u8);
for (upper, lower) in ('A'..='Z').zip('a'..='z') {
    to_lower[upper as usize] = lower as u8;
}
let mut text = *b"HELLO WORLD!";
sz::lookup_inplace(&mut text, to_lower);
assert_eq!(&text, b"hello world!");

lookup returns Status::UnexpectedDimensions, writing nothing, when the target is shorter than the source.

§ In Place Replacement

These rewrite a Vec<u8> in place, replacing either a literal needle or any byte from a Byteset with a replacement slice.

pub fn replace_all(buffer: &mut Vec<u8>, needle: &[u8], replacement: &[u8]) -> Result<usize, Status>;
pub fn replace_all_byteset(buffer: &mut Vec<u8>, byteset: Byteset, replacement: &[u8]) -> Result<usize, Status>;

Both replace all non-overlapping occurrences in place, returning the replacement count. Equal-length replacements overwrite, shorter ones compact forward without allocating, and longer ones resize once and rewrite from the back:

use stringzilla::{self as sz, Byteset};

let mut buffer = b"a-b-c".to_vec();
let n = sz::replace_all(&mut buffer, b"-", b"__").unwrap();
assert_eq!(n, 2);
assert_eq!(buffer, b"a__b__c");

let mut spaced = b"a, b ,c".to_vec();
sz::replace_all_byteset(&mut spaced, Byteset::from(", "), b"").unwrap();
assert_eq!(spaced, b"abc");

API

Functions

lookupPerforms a lookup-table transformation, mapping contents of a buffer into the same or other memory region, taking a byte substitution value from the provided table.
strings.rs:47 ↗
pub fn lookup<Target, Source>(
    target: &mut Target,
    source: &Source,
    table: [u8; 256],
) -> Result<(), Status>
where
    Target: AsMut<[u8]> + ?Sized,
    Source: AsRef<[u8]> + ?Sized,

Arguments

  • target: A mutable buffer to populate.
  • source: An immutable buffer to map from.
  • table: Lookup table of 256 substitution values.

Returns Status::UnexpectedDimensions if target is shorter than source.

Examples

To convert uppercase ASCII characters to lowercase:

use stringzilla as sz;
let mut to_lower: [u8; 256] = core::array::from_fn(|i| i as u8);
for (upper, lower) in ('A'..='Z').zip('a'..='z') {
    to_lower[upper as usize] = lower as u8;
}
let source = "HELLO WORLD!";
let mut target = vec![0u8; source.len()];
sz::lookup(&mut target, &source, to_lower).unwrap();
let result = String::from_utf8(target).expect("Invalid UTF-8 sequence");
assert_eq!(result, "hello world!");
lookup_inplacePerforms a lookup-table transformation, mapping contents of a buffer into the same or other memory region, taking a byte substitution value from the provided table.
strings.rs:93 ↗
pub fn lookup_inplace<Buffer>(buffer: &mut Buffer, table: [u8; 256])
where
    Buffer: AsMut<[u8]> + ?Sized,

Arguments

  • buffer: A mutable buffer to update inplace.
  • table: Lookup table of 256 substitution values.

Examples

use stringzilla as sz;
let mut to_lower: [u8; 256] = core::array::from_fn(|i| i as u8);
for (upper, lower) in ('A'..='Z').zip('a'..='z') {
    to_lower[upper as usize] = lower as u8;
}
let mut text = *b"HELLO WORLD!";
sz::lookup_inplace(&mut text, to_lower);
assert_eq!(text, *b"hello world!");
replace_allReplaces all non-overlapping occurrences of needle inside buffer in place.
strings.rs:295 ↗
pub fn replace_all(buffer: &mut Vec<u8>, needle: &[u8], replacement: &[u8]) -> Result<usize, Status>
  • equal-length replacements simply overwrite matches,
  • shorter replacements compact forward without allocating,
  • longer replacements count matches once, resize once, and rewrite from the back.

Returns the number of replacements performed.

replace_all_bytesetReplaces all non-overlapping bytes in buffer that belong to byteset with replacement.
strings.rs:322 ↗
pub fn replace_all_byteset(
    buffer: &mut Vec<u8>,
    byteset: Byteset,
    replacement: &[u8],
) -> Result<usize, Status>

Uses the same three-way strategy as replace_all. If the byteset is empty, the buffer is left untouched. Returns the number of replacements performed.