regex-split
Adds split_inclusive and split_inclusive_left methods to Rust's regex crate, matching std's string-splitting behavior for regex patterns.
Repository Health
Technical Analysis
regex-split extends Rust’s regex crate with split_inclusive and split_inclusive_left, two iterator-based splitting methods that keep the delimiter attached to each substring instead of discarding it. The standard library already offers split_inclusive for plain strings, but the regex crate has no equivalent for pattern-based splitting outside of an unstable nightly-only feature — this crate fills that gap on stable Rust.
The two methods differ only in where the matched delimiter ends up: split_inclusive appends it to the end of the preceding substring (mirroring str::split_inclusive), while split_inclusive_left prepends it to the following substring instead. Both are implemented as zero-copy iterators over &str (via the main module) or &[u8] (via the bytes submodule), built directly on top of regex::Regex::find_iter / regex::bytes::Regex::find_iter.
What You Get
- RegexSplit trait for
&str- addssplit_inclusiveandsplit_inclusive_leftmethods directly toregex::Regex - Byte-string variant - a
bytesmodule mirrors the same trait forregex::bytes::Regexand&[u8]input - Zero-copy iterators -
SplitInclusiveandSplitInclusiveLeftyield borrowed slices of the original text with no allocation - Fused iterator semantics - both iterator types implement
FusedIterator, so they behave predictably once exhausted
Common Use Cases
- Re-implementing
lines()with custom rules - split text on a regex like\r?\nwhile keeping the original line terminator attached to each line - Parsing delimiter-prefixed lists - split Markdown-style bullet lists (lines starting with
-) while keeping the marker attached to the following item viasplit_inclusive_left - Tokenizing log files or structured text - break a byte stream into chunks by a regex delimiter without losing which delimiter produced the boundary
- Parsing binary protocols - use the
bytesmodule to split raw&[u8]buffers on a byte-oriented regex pattern
Under The Hood
Architecture
The crate is a flat, single-purpose module pair: lib.rs defines the RegexSplit trait and its two iterator types (SplitInclusive, SplitInclusiveLeft) for &str, and bytes.rs is a near-exact structural duplicate operating on &[u8] via regex::bytes::Regex. Each iterator wraps a regex::Matches finder plus a last cursor and a reference to the source text, and next() advances the finder and slices between last and the new match boundary — the match’s end for SplitInclusive, its start for SplitInclusiveLeft. There is no dependency injection, branching control flow, or I/O; the only entry point is Regex::find_iter, so the entire crate’s behavior is governed by those two next() implementations, with the string and byte variants duplicating the same logic rather than sharing an abstraction.
Tech Stack
A minimal Rust crate targeting edition 2021 with a single runtime dependency, regex = "1.7.0", the officially maintained pattern-matching crate. There is no build tooling beyond stock cargo build, no database or network dependency, and no framework of any kind — it is published to crates.io with docs.rs-generated documentation, consumed as a library dependency rather than run as a service.
Code Quality
No dedicated test files or #[cfg(test)] modules exist anywhere in the repository — a grep for #[test] and mod tests under src/ returns nothing. The only verification present is doctested examples embedded in doc comments (assert_eq! blocks under //////!), which cargo test --doc would exercise but which don’t cover edge cases like empty input, no matches, or matches at string boundaries. Naming follows idiomatic Rust conventions (SplitInclusive, SplitInclusiveLeft mirroring the standard library’s own SplitInclusive), but there is no linter configuration and no CI workflow in the repository.
API Design
The public surface is deliberately tiny: import one trait, call one of two methods on an existing Regex, get back a standard iterator. This keeps boilerplate to essentially zero and the naming maps directly onto the standard library’s own str::split_inclusive, so anyone familiar with std’s API already knows how to use it. The tradeoff is that the crate replicates a capability that already exists — in std for strings, and behind an unstable flag inside regex itself — rather than introducing anything new; split_inclusive_left is the one genuinely original addition, since std has no direct equivalent.