Структура 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() - устаревший метод, используйте реализацию Display
  • cause() - устаревший метод, заменен на Error::source
  • provide() - экспериментальный метод для доступа к контексту ошибок

Пример использования в системе ошибок

#![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 принимает срез, а не владеющий вектор, поэтому нет возможности вернуть исходные данные.