必威体育Betway必威体育官网
当前位置:首页 > IT技术

rust中slice panicked at 'byte index 5 is not a char boundary' 问题解决办法

时间:2019-09-25 20:12:13来源:IT技术作者:seo实验室小编阅读:53次「手机版」
 

panicked

今天在工作中遇到一个问题,string调用truncate()接口panic了,报错信息大致如下:thread '0' panicked at 'assertion failed: self.is_char_boundary(new_len)', liballoc/string.rs:1121:13

我的代码如下:

示例1:

fn main() {
    let mut s = String::from("hello 中国");

    s.truncate(7); //获取前7个字节
    
    println!("s:{}", s);
}

------------------------------------------------------------------------
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.61s
     Running `target/debug/playground`
thread 'main' panicked at 'assertion failed: self.is_char_boundary(new_len)', src/liballoc/string.rs:1123:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

当然原始代码不是这个,但是原理是一样的。这里的问题出现在字符串中的中文(纯英文字符不会出现panic)。原因是,一个汉字所在字节数为非1 byte,当去截取slice的中字符时,字符边界判断导致panic了。

一开始怀疑是truncate()接口的问题,但后来发现并不是truncate本身的问题,所有涉及到slice中截取中文字符都会容易导致panic,不信看下面例子:

示例2:

fn main() {
    let a = "abcd早";
    let b = &a[..5];
    
    println!("b={}", b);
}

-------------------------------------------------------------------------
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.51s
     Running `target/debug/playground`
thread 'main' panicked at 'byte index 5 is not a char boundary; it is inside '早' (bytes 4..7) of `abcd早`', src/libcore/str/mod.rs:2027:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

再看如下例子:

示例3:

fn main() {
    let a = "abcd早";
    let b = &a[..3];
    
    println!("b={}", b);
}

--------------------------------------------------------------
输出结果:
b=abc

示例4:

fn main() {
    let a = "abcd早";
    let b = &a[..7];
    
    println!("b={}", b);
}

-------------------------------------------------------------
输出结果:
b=abcd早

示例3与示例2的区别在于,截取的字节数不同。示例3截取前3个字符均是英文,而示例4正好截取到了中文“早”字的字符边界(“早”字占4个字节)。

那么实际生产环境中很难保证我们要截取的slice中没有中文字符,任意截取不能保证正好是字符边界,那该怎么办?

网上有人提到先把slice转换为chars的vector,然后再调用truncate()之类的,但是觉得这样太消耗性能,所以我得方法是:

// 首先判断给出的index是不是字符边界,否则向后找到字符边界所在位置
fn find_char_boundary(s: &str, index: usize) -> usize {
    if s.len() <= index {
        return index;
    }
    
    let mut new_index = index;
    while !s.is_char_boundary(new_index) {
        new_index += 1;
    }
    
    new_index
}


fn main() {
    let mut s = String::from("hello 中国");
    let idx = find_char_boundary(&s, 7); //实际获取到的idx=9
    
    s.truncate(idx);
    
    println!("idx:{}, s:{}", idx, s);
}


-------------------------------------------------------------------
输出结果:
idx:9, s:hello 中

好了,以上就是对自己在rust编程中遇到的问题,做一个总结与备忘,希望对有需要的人也能够有所帮助!

相关阅读

字符串查询功能 patindex与charindex的区别

patindex(pattern,expression) 精确匹配   完全匹配返回1,不完全匹配返回0 patindex('aa','aa')  返回1patindex('aa','aabb')

jquery之index与selectedIndex

晚上有时间,继续再写一点,我们来讲一下关于select表单的所有操作,在项目中还是有很多地方需要用到的。 讲select之前先讲一下index()的

java.lang.StringIndexOutOfBoundsException: String

字符串截取下标越界   出错代码 @GetMapping("/edit") //@RequiresPermissions("erp:enquirySheet:edit") public String

mybatis Parameter index out of range (1 > number o

今天遇到了一个有意思的问题,看错误信息提示,好像是有个参数没有匹配上,具体错误信息如下: ### SQL: SELECT count(*) FROM (SELECT

indexOf用法

分享到:

栏目导航

推荐阅读

热门阅读