В то время как Rust предоставляет str.as_bytes
, я хочу скопировать строку в буфер фиксированного размера, где в буфер скопированы только полные значения unicode-scalar и вместо этого усечены с нулевым терминатором, написанным в конце, в C термины, я бы назвал это utf8
осведомленным strlcpy
(то есть - он копирует в буфер фиксированного размера и обеспечивает его завершение нулем).Эффективная усеченная строка копирует `str` в` [u8] `(utf8 aware strlcpy)?
Это функция, которую я придумал, но я полагаю, есть лучшие способы сделать это в Русте:
// 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
.
Не было бы лучше написать 'let mut last_index = :: std :: cmp :: min (utf8_dst_len - 1, str_src.len());' для второго примера? Таким образом, он не подсчитывает один за другим, когда строка меньше, чем '[u8]'? – ideasman42
Да, спасибо - обновлено. –
Отдайте предпочтение этой версии второго примера: https://bitbucket.org/snippets/ideasman42/GqB8o - возможно, это просто личное предпочтение, но оно позволяет избежать запуска 'is_char_boundary', когда это не нужно, что делает его более явным, когда строка должна быть усечена. – ideasman42