rs.nkmk.me

Rustで&strと&[u8]を相互に変換

Posted: | Tags: Rust, 文字列

Rustにおいて、文字列スライス&strはUTF-8として有効なバイト列のスライス&[u8]である。&str&[u8]を相互に変換するにはas_bytesstr::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_utf8from_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😀");

関連カテゴリー

関連記事