Есть ли разница между str :: as_bytes и CString :: as_bytes_with_nul? - PullRequest
0 голосов
/ 09 февраля 2019

Есть ли разница между этим:

name.as_bytes()

и этим:

CString::new(name)?.as_bytes_with_nul()

Я хочу получить байты от name (что составляет String) вспособ, которым я могу легко отправить их по сети, и я не уверен, нужен ли здесь CString.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Пока в вашей строке нет 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.

0 голосов
/ 09 февраля 2019

Документация as_bytes_with_nul начинается с:

Эквивалентна функции as_bytes, за исключением того, что возвращаемый фрагмент включает в себя завершающий нулевой терминатор.

Пока as_bytes равно:

В возвращенном срезе не содержится завершающий нулевой терминатор

(выделено в оригинальной цитате)

Вам решать, нужно ли передавать нулевой байт, и это зависит от того, как вы отправляете данные по сети (TCP / UDP - rawдвоичные данные через TCP (если да, как вы собираетесь разделять сообщения? JSON? и т. д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...