Пока в вашей строке нет 0
кодовой единицы UTF-8, name.as_bytes()
и CString::new(name)?.as_bytes()
должны давать вам одинаковые байты.Кроме того, CString
.as_bytes_with_null()
просто добавит 0
байт.Вот небольшая демонстрация с довольно сложной строкой UTF-8:
use std::ffi::CString;
fn main() {
let message: String = "\nßщ\u{1F601}".to_string();
println!("bytes_1: {:?}", message.as_bytes());
println!("bytes_2: {:?}", CString::new(message.clone()).unwrap().as_bytes());
println!("bytes_3: {:?}", CString::new(message.clone()).unwrap().as_bytes_with_nul());
}
Результат соответствует ожидаемому (вы можете узнать 10
, что соответствует ASCII-символу \n
, которыйзакодирован таким же образом в UTF-8):
bytes_1: [10, 195, 159, 209, 137, 240, 159, 152, 129]
bytes_2: [10, 195, 159, 209, 137, 240, 159, 152, 129]
bytes_3: [10, 195, 159, 209, 137, 240, 159, 152, 129, 0]
Проблема возникает, если ваша строка содержит U+0000
, , которая является допустимой кодовой точкой Unicode , кодируется одним байтом 0
в UTF-8
и может встречаться в обычных строках.Например:
use std::ffi::CString;
fn main() {
let message: String = "\n\u{0000}\n\u{0000}".to_string();
println!("bytes_1: {:?}", message.as_bytes());
println!(
"bytes_2: {:?}",
match CString::new(message.clone()) {
Err(e) => format!("an error: {:?}, as expected", e),
Ok(_) => panic!("won't happen. .as_bytes() must fail."),
}
);
}
даст вам
bytes_1: [10, 0, 10, 0]
bytes_2: "an error: NulError(1, [10, 0, 10, 0]), as expected"
Итак, простой .as_bytes()
успешен, но версия CString
не выполнена.Я бы порекомендовал придерживаться name.as_bytes()
и UTF-8, если это возможно, нет оснований сначала конвертировать его в CString.