Rustで&strと&[u8]を相互に変換
Rustにおいて、文字列スライス&str
はUTF-8として有効なバイト列のスライス&[u8]
である。&str
と&[u8]
を相互に変換するにはas_bytes
やstr::from_utf8
を使う。
Vec<u8>
とString
の相互変換については以下の記事を参照。String::from_utf8_lossy
には&[u8]
も渡せる。
以下のサンプルコードでは、説明のため、型推論によって省略できるときも明示的に型注釈を記述している場合がある。また、簡単のためunwrap
を使っている。必要であればその他のメソッドやmatch
などで処理すればよい。
&strを&[u8]に変換: as_bytes
&str
を&[u8]
に変換するにはas_bytes
メソッドを使う。
let s: &str = "abc😀";
let b: &[u8] = s.as_bytes();
assert_eq!(b, [97, 98, 99, 240, 159, 152, 128]);
ちなみに似た名前のbytes
メソッドもあるが、こちらはバイトu8
のイテレータを返す。
&[u8]を&strに変換: str::from_utf8
&[u8]
を&str
に変換するにはstd::str::from_utf8
を使う。
&str
はUTF-8として有効であることが保証されている(=有効でなければいけない)。したがって、UTF-8として有効な&[u8]
は&str
に変換できるが、有効でない場合は変換できない。
from_utf8
の返り値の型はResult
。UTF-8として有効でないバイト列に対してはエラーを返す。
let b: [u8; 7] = [97, 98, 99, 240, 159, 152, 128];
let s: &str = std::str::from_utf8(&b).unwrap();
assert_eq!(s, "abc😀");
let b: [u8; 4] = [97, 98, 99, 255];
let is_err: bool = std::str::from_utf8(&b).is_err();
assert!(is_err);
unsafe
な関数として、UTF-8として有効かどうかのチェックを行わないstd::str::from_utf8_unchecked
も提供されている。UTF-8として有効であることが確実で、チェックのためのオーバーヘッドを避けたい場合に使う。
let b: [u8; 7] = [97, 98, 99, 240, 159, 152, 128];
let s: &str = unsafe { std::str::from_utf8_unchecked(&b) };
assert_eq!(s, "abc😀");
なお、from_utf8
とfrom_utf8_unchecked
の引数の型はバイトのスライス&[u8]
なので、配列とベクタの参照(&[u8; N]
, &Vec<u8>
)も渡せる。
実際に、上の例では配列の参照&[u8; N]
を渡している。
&Vec<u8>
を渡す例は以下の通り。
let v: Vec<u8> = vec![97, 98, 99, 240, 159, 152, 128];
let s: &str = std::str::from_utf8(&v).unwrap();
assert_eq!(s, "abc😀");
ちなみに、b"..."
の形でバイト列リテラルを生成できる。バイト列リテラルの型は&'static [u8; N]
。
The type of a byte string literal of length
n
is&'static [u8; n]
. Tokens - Byte string literals - The Rust Reference
let b: &'static [u8; 7] = b"abc\xF0\x9F\x98\x80";
let s: &str = std::str::from_utf8(b).unwrap();
assert_eq!(s, "abc😀");