转换Vec 或者Vec 它a&p

问题描述 投票:6回答:2

我正在进入Rust编程实现一个小程序,我在字符串转换中有点迷失。

在我的程序中,我有一个向量如下:

let mut name: Vec<winnt::WCHAR> = Vec::new(); 

WCHAR和我的Windows机器上的u16相同。

我将Vec<u16>移交给C函数(作为指针),用它填充数据。然后我需要将矢量中包含的字符串转换为&str。但是,无论我尝试什么,我都无法让这种转换工作。

我设法工作的唯一方法是将其转换为WideString

 widestr = unsafe { WideCString::from_ptr_str(name.as_ptr()) };

但这似乎是走向错误方向的一步。

在假设向量包含有效且以null结尾的字符串的情况下,将Vec<u16>转换为&str的最佳方法是什么?

string rust
2个回答
11
投票

然后我需要将矢量中包含的字符串转换为&str。但是,无论我尝试什么,我都无法让这种转换工作。

没有办法让这个“免费”转换。

&str是用UTF-8编码的Unicode字符串。这是一种面向字节的编码。如果您有UTF-16(或不同但常见的UCS-2编码),则无法读取另一个。这相当于尝试将JPEG图像作为PDF读取。两个数据块都可能是一个字符串,但编码很重要。

第一个问题是“你真的需要这样做吗?”。很多时候,您可以从一个函数中获取数据并将其转换回另一个函数,从不查看它。如果你可以逃脱,那可能是最好的答案。

如果您确实需要对其进行转换,则必须处理可能发生的错误。任意16位整数数组可能不是有效的UTF-16或UCS-2。这些编码具有边缘情况,可以轻松生成无效字符串。空终止是另一个方面 - Unicode实际上允许嵌入的NUL字符,因此以null结尾的字符串不能容纳所有可能的Unicode字符!

一旦确保编码有效1并确定输入向量中有多少条目构成字符串,则必须解码输入格式并重新编码为输出格式。这可能需要某种新的分配,所以你最有可能最终得到一个String,然后可以在任何可以使用&str的地方使用。

有一种内置的方法可以将UTF-16数据转换为String:String::from_utf16。请注意,它返回Result以允许这些错误情况。还有String::from_utf16_lossy,它用Unicode替换字符替换无效的编码部分。

let name = [0x68, 0x65, 0x6c, 0x6c, 0x6f]; 

let a = String::from_utf16(&name);
let b = String::from_utf16_lossy(&name);

println!("{:?}", a);
println!("{:?}", b);

如果您从指向u16WCHAR的指针开始,则需要先使用slice::from_raw_parts转换为切片。如果你有一个以null结尾的字符串,你需要自己找到NUL并适当地切片输入。


1:这实际上是一种使用类型的好方法;保证&str采用UTF-8编码,因此无需进一步检查。同样,WideCString可能会在施工时执行一次检查,然后可以跳过以后使用的检查。


0
投票

这是我对这个案子的简单攻击。必须有一个bug;修复你自己的情况:

let mut v = vec![0u16; MAX_PATH as usize];

// imaginary win32 function
win32_function(v.as_mut_ptr());

let mut path = String::new();
for val in v.iter() {
    let c: u8 = (*val & 0xFF) as u8;
    if c == 0 {
        break;
    } else {
        path.push(c as char);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.