gpt4 book ai didi

string - 高效截断字符串复制 `str` 到 `[u8]`(utf8 识别 strlcpy)?

转载 作者:行者123 更新时间:2023-11-29 08:14:23 25 4
gpt4 key购买 nike

虽然 Rust 提供了 str.as_bytes,但我希望将一个字符串复制到一个固定大小的缓冲区中,其中只有完整的 unicode-scalar-values 被复制到缓冲区中,而不是被截断一个写在最后的空终止符,用 C 术语来说,我称之为 utf8 感知 strlcpy (即 - 它复制到一个固定大小的缓冲区中并且确保它的 null 终止)


这是我想出的一个函数,但我希望在 Rust 中有更好的方法来做到这一点:

// return the number of bytes written to
pub fn strlcpy_utf8(utf8_dst: &mut [u8], str_src: &str) -> usize {
let utf8_dst_len = utf8_dst.len();
if utf8_dst_len == 0 {
return 0;
}
let mut index: usize = 0;
if utf8_dst_len > 1 {
let mut utf8_buf: [u8; 4] = [0; 4];
for c in str_src.chars() {
let len_utf8 = c.len_utf8();
let index_next = index + len_utf8;
c.encode_utf8(&mut utf8_buf);
if index_next >= utf8_dst_len {
break;
}
utf8_dst[index..index_next].clone_from_slice(&utf8_buf[0..len_utf8]);
index = index_next;
}
}
utf8_dst[index] = 0;
return index + 1;
}

注意):我意识到这并不理想,因为多个 UCS 可能构成一个字形,但是结果至少能够解码回str.

最佳答案

Rust 的 str 有一个方便的方法 char_indices当你需要知道实际的字符边界时。这会立即在一定程度上简化您的功能:

pub fn strlcpy_utf8(utf8_dst: &mut [u8], str_src: &str) -> usize {
let utf8_dst_len = utf8_dst.len();
if utf8_dst_len == 0 {
return 0;
}
let mut last_index = 0;
for (idx, _) in str_src.char_indices() {
if (idx+1) > utf8_dst_len {
break;
}
last_index = idx;
}
utf8_dst[0..last_index].copy_from_slice(&str_src.as_bytes()[0..last_index]);
utf8_dst[last_index] = 0;
return last_index + 1;
}

Playground

然而,除了复制时,您实际上不需要遍历每个字符,因为在 UTF8 中很容易找到边界; Rust 有 str::is_char_boundary() .这让您可以从头往后看:

pub fn strlcpy_utf8(utf8_dst: &mut [u8], str_src: &str) -> usize {
let utf8_dst_len = utf8_dst.len();
if utf8_dst_len == 0 {
return 0;
}
let mut last_index = min(utf8_dst_len-1, str_src.len());
while last_index > 0 && !str_src.is_char_boundary(last_index) {
last_index -= 1;
}
utf8_dst[0..last_index].copy_from_slice(&str_src.as_bytes()[0..last_index]);
utf8_dst[last_index] = 0;
return last_index + 1;
}

Playground

关于string - 高效截断字符串复制 `str` 到 `[u8]`(utf8 识别 strlcpy)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42063162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com