#text #streaming #line #lines #line-end

no-std line-span

Find line ranges and jump between next and previous lines

6 releases

0.1.5 Jun 12, 2023
0.1.4 Jun 12, 2023
0.1.3 Aug 25, 2021
0.1.2 Feb 21, 2020

#141 in Algorithms

Download history 593/week @ 2023-10-27 601/week @ 2023-11-03 611/week @ 2023-11-10 503/week @ 2023-11-17 488/week @ 2023-11-24 443/week @ 2023-12-01 353/week @ 2023-12-08 399/week @ 2023-12-15 553/week @ 2023-12-22 445/week @ 2023-12-29 444/week @ 2024-01-05 536/week @ 2024-01-12 655/week @ 2024-01-19 386/week @ 2024-01-26 425/week @ 2024-02-02 534/week @ 2024-02-09

2,075 downloads per month
Used in 22 crates (7 directly)

MIT license

369 lines


CI Latest Version Docs License

This crate features utilities for finding the start, end, and range of lines from a byte index. Further also being able to find the next and previous line, from an arbitrary byte index.

This is provided via the trait LineSpanExt, which is implemented for str, and provides the following methods:


Add this to your Cargo.toml:

line-span = "0.1"


Release notes are available in the repo at CHANGELOG.md.

Current Line:

Next Line:

Previous Line:


LineSpan and LineSpanIter

The crate includes the LineSpanIter iterator. It is functionally equivalent to str::lines(), with the addition that it includes the ability to get the start and end byte indices of each line. Additionally, it also includes the ability to get the end including and excluding the line ending (\n or \r\n).

An LineSpanIter can be created by calling line_spans(), implemented in the LineSpans trait. The crate implements the LineSpans trait for str and String.

Note, LineSpan implements Deref to &str, so in general, swapping lines() to line_spans() would not cause many issues.

use line_span::LineSpans;

let text = "foo\nbar\r\nbaz";

for span in text.line_spans() {
        "{:>2?}: {:?} {:?} {:?}",

This will output the following:

(Manually aligned for better readability)

0.. 3: "foo" "foo\n"   "\n"
4.. 7: "bar" "bar\r\n" "\r\n"
9..12: "baz" "baz"     ""

Current Line, Previous Line, and Next Line

use line_span::LineSpanExt;

let text = "foo\nbar\r\nbaz";
//                ^
let i = 5; // 'a' in "bar"

let curr_range = text.find_line_range(i);
let next_range = text.find_next_line_range(i).unwrap();
let prev_range = text.find_prev_line_range(i).unwrap();

assert_eq!(curr_range, 4..7);
assert_eq!(&text[curr_range], "bar");

assert_eq!(prev_range, 0..3);
assert_eq!(&text[prev_range], "foo");

assert_eq!(next_range, 9..12);
assert_eq!(&text[next_range], "baz");

Range of Substring in String

Use str_to_range (or str_to_range_unchecked) to get the range of a substring in a string.

let string1 = "Foo Bar Baz";
let string2 = "Hello World";

let substring = &string1[4..7]; // "Bar"

// Returns `Some` as `substring` is a part of `string1`
assert_eq!(str_to_range(string1, substring), Some(4..7));

// Returns `None` as `substring` is not a part of `string2`
assert_eq!(str_to_range(string2, substring), None);

No runtime deps