给定一个字符串和一个引用某个子字符串的切片,是否可以找到切片的开始和结束索引?
我有一个ParseString函数,它接受一个字符串的引用,并尝试根据某种语法解析它:
ParseString(inp_string: &str) -> Result<(), &str>
Run Code Online (Sandbox Code Playgroud)
如果解析没问题,结果就是Ok(()),但如果有错误,它通常在某个子字符串中,错误实例是Err(e),其中e是该子字符串的一个切片。
当给出发生错误的子字符串时,我想说类似“从字符 x 到 y 的错误”之类的内容,其中 x 和 y 是错误子字符串的开始和结束索引。
我不想直接在 中编码错误的位置Err,因为我嵌套了这些调用,并且嵌套切片中的偏移量可能与顶级字符串中的某个切片不对应。
只要您的所有字符串切片都从同一个字符串缓冲区借用,您就可以使用简单的指针算法计算偏移量。您需要以下方法:
str::as_ptr(): 返回指向字符串切片开头的指针usize(始终是空操作)然后减去它们。每晚,有一种不稳定的方法offset_from(),稍微好一点。这是工作代码(Playground):
fn get_range(whole_buffer: &str, part: &str) -> (usize, usize) {
let start = part.as_ptr() as usize - whole_buffer.as_ptr() as usize;
let end = start + part.len();
(start, end)
}
fn main() {
let input = "Everyone ? Ümläuts!";
let part1 = &input[1..7];
println!("'{}' has offset {:?}", part1, get_range(input, part1));
let part2 = &input[7..16];
println!("'{}' has offset {:?}", part2, get_range(input, part2));
}
Run Code Online (Sandbox Code Playgroud)
Rust 实际上曾经有一种不稳定的方法来做到这一点,但由于已经过时而被删除,考虑到替代品远程没有相同的功能,这有点奇怪。
也就是说,实现并不是那么大,因此您可以将以下内容添加到您的代码中:
pub trait SubsliceOffset {
/**
Returns the byte offset of an inner slice relative to an enclosing outer slice.
Examples
```ignore
let string = "a\nb\nc";
let lines: Vec<&str> = string.lines().collect();
assert!(string.subslice_offset_stable(lines[0]) == Some(0)); // &"a"
assert!(string.subslice_offset_stable(lines[1]) == Some(2)); // &"b"
assert!(string.subslice_offset_stable(lines[2]) == Some(4)); // &"c"
assert!(string.subslice_offset_stable("other!") == None);
```
*/
fn subslice_offset_stable(&self, inner: &Self) -> Option<usize>;
}
impl SubsliceOffset for str {
fn subslice_offset_stable(&self, inner: &str) -> Option<usize> {
let self_beg = self.as_ptr() as usize;
let inner = inner.as_ptr() as usize;
if inner < self_beg || inner > self_beg.wrapping_add(self.len()) {
None
} else {
Some(inner.wrapping_sub(self_beg))
}
}
}
Run Code Online (Sandbox Code Playgroud)
_stable如果不需要支持旧版本的 Rust,可以去掉后缀;它只是为了避免与现已删除的subslice_offset方法发生名称冲突。