How to get the byte offset between `&str`

2019-02-25 02:30发布

问题:

I have two &str pointing to the same string, and I need to know the byte offset between them:

fn main() {
    let foo = "  bar";
    assert_eq!(offset(foo, foo.trim()), Some(2));

    let bar = "baz\nquz";
    let mut lines = bar.lines();
    assert_eq!(offset(bar, lines.next().unwrap()), Some(0));
    assert_eq!(offset(bar, lines.next().unwrap()), Some(4));

    assert_eq!(offset(foo, bar), None); // not a sub-string

    let quz = "quz".to_owned();
    assert_eq!(offset(bar, &quz), None); // not the same string, could also return `Some(4)`, I don't care
}

This is basically the same as str::find, but since the second slice is a sub-slice of the first, I would have hoped about something faster. Also str::find won't work in the lines() case if several lines are identical.

I thought I could just use some pointer arithmetic to do that with something like foo.trim().as_ptr() - foo.as_ptr() but it turns out that Sub is not implemented on raw pointers.

回答1:

but it turns out that Sub is not implemented on raw pointers.

You can convert the pointer to a usize to do math on it:

fn main() {
    let source = "hello, world";
    let a = &source[1..];
    let b = &source[5..];
    let diff =  b.as_ptr() as usize - a.as_ptr() as usize;
    println!("{}", diff);
}


回答2:

This is of course kind of unsafe, but if you want arithmetic, you can just cast the pointers to usize with as and subtract that.

(Note: it's not so unsafe that the compiler will actually complain.)



标签: rust