Skip to content

mskvarc/pct

Repository files navigation

pct

Crate Docs MSRV License

A small, allocation-conscious Rust crate for percent-encoded strings used in URLs, URIs, IRIs, etc. — parse, validate, encode, decode, compare.

use pct::{PctStr, PctString, UriReserved};

let s = PctStr::new("Hello%20World%21")?;
assert_eq!(s, "Hello World!");
assert_eq!(s.decode(), "Hello World!");

let encoded = PctString::encode("Hello World!".chars(), UriReserved::Any);
assert_eq!(encoded.as_str(), "Hello%20World%21");

Pick an Encoder impl (UriReserved, IriReserved) or write your own:

use pct::{Encoder, PctString, UriReserved};

struct Upper;
impl Encoder for Upper {
    fn encode(&self, c: char) -> bool {
        UriReserved::Any.encode(c) || c.is_uppercase()
    }
}

let s = PctString::encode("Hello World!".chars(), Upper);
assert_eq!(s.as_str(), "%48ello%20%57orld%21");

Why this fork

Fork of pct-str by Timothée Haudebourg. Public API and RFC behavior unchanged; this fork adds:

  • SWAR plain-run scanner and portable-SIMD path (nightly, gated on simd) for validate / decode / encode.
  • Hex-decode lookup tables replacing per-nibble branches.
  • Byte-level fast paths for new, decode, encode_bytes, eq, ord, hash, len.
  • memchr-accelerated % scan (default-on).
  • Criterion bench suite under benches/.
  • Rust 2024 edition, MSRV 1.85.
  • Renamed crate to pct.

Credit and history preserved — see Attribution.

Install

cargo add pct

Feature flags

Flag Default Enables
std yes std::error::Error impls, owned PctString, String APIs
memchr yes memchr-accelerated % scan in validate / decode / encode
simd Portable-SIMD plain-run scanner. Requires nightly rustc.

For no_std, disable default features. You get PctStr (borrowed, zero-alloc) and the Encoder trait. Re-enable std for PctString and String-returning APIs.

Streaming decode

PctStr::chars() and PctStr::bytes() are lazy iterators over the decoded form. No intermediate String, works under no_std:

let s = pct::PctStr::new("caf%C3%A9")?;
for ch in s.chars() { /* 'c', 'a', 'f', 'é' */ }

For encoding from a known &str, prefer PctString::encode_bytes — it skips UTF-8 re-iteration and hits the SWAR/SIMD scanner directly.

Equivalence

Equality, ordering, and hashing compare the decoded bytes — PctStr::new("%41") == "A", and hex case (%2f vs %2F) is irrelevant. Keep this in mind when using PctStr / PctString as map keys: two values with different as_str() can hash equal.

Examples

See examples/ for runnable end-to-end usage:

cargo run --example encode
cargo run --example str
cargo run --example string

Benchmarks

cargo bench
cargo +nightly bench --features simd

Criterion output: target/criterion/.

MSRV

Rust 1.85 (edition 2024). The simd feature additionally requires nightly.

Attribution

Original crate: pct-str by Timothée Haudebourg. Upstream commits are preserved in this repo's history under their original authorship. This fork is a thin layer of performance and ergonomics work on top of their design.

License

Dual-licensed, same as upstream. Pick whichever fits:

About

Percent-encoded strings for URL, URI, IRI, etc.

Resources

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE-APACHE.md
MIT
LICENSE-MIT.md

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages