How to convert Rust strings to UTF-16?
Rust 1.8+
str::encode_utf16
is the stable iterator of UTF-16 values.
You just need to use collect()
on that iterator to construct Vec<u16>
and then push(0)
on that vector:
pub fn main() {
let s = "Hello";
let mut v: Vec<u16> = s.encode_utf16().collect();
v.push(0);
}
Rust 1.0+
str::utf16_units()
/ str::encode_utf16
is unstable. The alternative is to either switch to nightly (a viable option if you're writing a program, not a library) or to use an external crate like encoding:
extern crate encoding;
use std::slice;
use encoding::all::UTF_16LE;
use encoding::{Encoding, EncoderTrap};
fn main() {
let s = "Hello";
let mut v: Vec<u8> = UTF_16LE.encode(s, EncoderTrap::Strict).unwrap();
v.push(0); v.push(0);
let s: &[u16] = unsafe { slice::from_raw_parts(v.as_ptr() as *const _, v.len()/2) };
println!("{:?}", s);
}
(or you can use from_raw_parts_mut
if you want a &mut [u16]
).
However, in this particular example you have to be careful with endianness because UTF_16LE
encoding gives you a vector of bytes representing u16
's in little endian byte order, while the from_raw_parts
trick allows you to "view" the vector of bytes as a slice of u16
's in your platform's byte order, which may as well be big endian. Using a crate like byteorder
may be helpful here if you want complete portability.
This discussion on Reddit may also be helpful.
Rust 1.46+
For static UTF-16 strings, the utf16_lit
crate provides an easy to use macro to do this at compile time:
use utf16_lit::utf16_null;
fn main() {
let s = &utf16_null!("Hello");
println!("{:?}", s);
}