Структура FromUtf16Error
Описание
Возможное значение ошибки при преобразовании String из среза UTF-16 байт.
Этот тип является типом ошибки для метода from_utf16 у String.
Синтаксис
#![allow(unused)] fn main() { pub struct FromUtf16Error(/* приватные поля */); }
Примеры
#![allow(unused)] fn main() { // 𝄞mu<invalid>ic let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; assert!(String::from_utf16(v).is_err()); }
Примеры использования
Базовое использование
#![allow(unused)] fn main() { // Валидная UTF-16 последовательность let valid_utf16: &[u16] = &[0x0048, 0x0065, 0x006C, 0x006C, 0x006F]; // "Hello" let result = String::from_utf16(valid_utf16); assert!(result.is_ok()); assert_eq!(result.unwrap(), "Hello"); // Невалидная UTF-16 последовательность (одиночный surrogate) let invalid_utf16: &[u16] = &[0xD800, 0x0061]; // одинокий high surrogate let result = String::from_utf16(invalid_utf16); assert!(result.is_err()); }
Обработка ошибок
#![allow(unused)] fn main() { fn process_utf16_data(data: &[u16]) -> Result<String, FromUtf16Error> { String::from_utf16(data) } let test_data = &[0xD834, 0xDD1E, 0x006D, 0x0075, 0xD800]; // невалидный surrogate match process_utf16_data(test_data) { Ok(string) => { println!("Успешно преобразовано: {}", string); } Err(e) => { println!("Ошибка преобразования UTF-16: {}", e); // К сожалению, FromUtf16Error не предоставляет методов для доступа к исходным данным // в отличие от FromUtf8Error } } }
Сравнение с FromUtf8Error
#![allow(unused)] fn main() { // FromUtf8Error предоставляет доступ к исходным байтам let utf8_bytes = vec![0xFF, 0xFE]; // невалидный UTF-8 if let Err(e) = String::from_utf8(utf8_bytes) { println!("Невалидные UTF-8 байты: {:?}", e.as_bytes()); } // FromUtf16Error не предоставляет аналогичных методов let utf16_data = &[0xD800]; // невалидный UTF-16 if let Err(e) = String::from_utf16(utf16_data) { println!("Ошибка UTF-16: {}", e); // Нет методов для доступа к исходным u16 данным } }
Реализации трейтов
Debug
#![allow(unused)] fn main() { impl Debug for FromUtf16Error }
Позволяет форматирование FromUtf16Error для отладки.
Пример
#![allow(unused)] fn main() { let invalid_data = &[0xD800]; let error = String::from_utf16(invalid_data).unwrap_err(); println!("Отладочная информация: {:?}", error); }
Display
#![allow(unused)] fn main() { impl Display for FromUtf16Error }
Позволяет пользовательское форматирование FromUtf16Error для отображения.
Пример
#![allow(unused)] fn main() { let invalid_data = &[0xD800]; let error = String::from_utf16(invalid_data).unwrap_err(); println!("Сообщение об ошибке: {}", error); }
Error
#![allow(unused)] fn main() { impl Error for FromUtf16Error }
Реализует трейт ошибки, позволяя использование в системах обработки ошибок Rust.
Методы:
source()- возвращает низкоуровневый источник этой ошибки, если естьdescription()- устаревший метод, используйте реализациюDisplaycause()- устаревший метод, заменен наError::sourceprovide()- экспериментальный метод для доступа к контексту ошибок
Пример использования в системе ошибок
#![allow(unused)] fn main() { use std::error::Error; fn handle_utf16_conversion(data: &[u16]) -> Result<(), Box<dyn Error>> { let _string = String::from_utf16(data)?; Ok(()) } let bad_data = &[0xD800]; if let Err(e) = handle_utf16_conversion(bad_data) { println!("Произошла ошибка: {}", e); if let Some(source) = e.source() { println!("Источник ошибки: {}", source); } } }
Автоматические реализации трейтов
Freeze for FromUtf16Error- может быть замороженRefUnwindSafe for FromUtf16Error- безопасен для паникиSend for FromUtf16Error- может быть передан между потокамиSync for FromUtf16Error- может быть разделен между потокамиUnpin for FromUtf16Error- может быть безопасно перемещеноUnwindSafe for FromUtf16Error- безопасен для паники
Особенности UTF-16
Валидные последовательности UTF-16
#![allow(unused)] fn main() { // Валидные символы BMP (Basic Multilingual Plane) let bmp_chars: &[u16] = &[0x0041, 0x0042, 0x0043]; // "ABC" assert!(String::from_utf16(bmp_chars).is_ok()); // Валидные surrogate пары для символов вне BMP let surrogate_pair: &[u16] = &[0xD834, 0xDD1E]; // музыкальный символ 𝄞 assert!(String::from_utf16(surrogate_pair).is_ok()); }
Невалидные последовательности UTF-16
#![allow(unused)] fn main() { // Одинокий high surrogate let lone_high: &[u16] = &[0xD800]; assert!(String::from_utf16(lone_high).is_err()); // Одинокий low surrogate let lone_low: &[u16] = &[0xDC00]; assert!(String::from_utf16(lone_low).is_err()); // Неправильный порядок surrogate let wrong_order: &[u16] = &[0xDD1E, 0xD834]; // low перед high assert!(String::from_utf16(wrong_order).is_err()); }
Практическое применение
Чтение данных из внешних источников
#![allow(unused)] fn main() { fn read_utf16_from_file(path: &str) -> Result<String, Box<dyn std::error::Error>> { use std::fs::File; use std::io::Read; let mut file = File::open(path)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; // Предполагаем, что данные little-endian UTF-16 let u16_data: Vec<u16> = buffer .chunks_exact(2) .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) .collect(); String::from_utf16(&u16_data).map_err(|e| e.into()) } }
Обработка данных Windows API
#![allow(unused)] fn main() { #[cfg(windows)] fn get_windows_error_message() -> Result<String, FromUtf16Error> { use winapi::um::winbase::FormatMessageW; use winapi::um::winbase::FORMAT_MESSAGE_ALLOCATE_BUFFER; use winapi::um::winbase::FORMAT_MESSAGE_FROM_SYSTEM; use winapi::um::winbase::FORMAT_MESSAGE_IGNORE_INSERTS; use std::ptr; unsafe { let mut buffer: *mut u16 = ptr::null_mut(); let size = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, ptr::null_mut(), // код ошибки... 0, 0, &mut buffer as *mut *mut u16 as *mut u16, 0, ptr::null_mut() ); if size > 0 { let slice = std::slice::from_raw_parts(buffer, size as usize); let result = String::from_utf16(slice); // освобождение памяти... result } else { // обработка ошибки... } } } }
Ограничения
В отличие от FromUtf8Error, структура FromUtf16Error не предоставляет методов для доступа к исходным данным, которые вызвали ошибку. Это связано с тем, что метод from_utf16 принимает срез, а не владеющий вектор, поэтому нет возможности вернуть исходные данные.