本記事では文字列スライス str
から文字列 String
に変換する方法とその仕組みについてまとめます。
文字列 String
から文字列スライス str
への変換については別記事にしました。
参考「[Rust] 文字列 String から文字列スライス str へ変換される仕組み - Qiita」
0. まとめ
let ss: &str = "str";
let s = ss.to_string();
// or
let s = String::from(ss);
// or
let s: String = ss.into();
// or
let s = ss.to_owned();
-
String::from
はstr::to_owned
を呼ぶ -
str::into
はString::from
を呼ぶ -
str::to_string
はString::from
を呼ぶ
let ss: &str = "str";
// 文字列置換を伴う型変換
let s_replaced = ss.replace("str", "String");
// or
let s_replaced = ss.replacen("str", "String", 1);
// 繰り返しを伴う型変換
let s_repeated = ss.repeat(3);
// 大文字・小文字変換を伴う型変換
let s_ascii_lowercase = ss.to_ascii_lowercase();
// or
let s_ascii_uppercase = ss.to_ascii_uppercase();
// or
let s_uppercase = ss.to_uppercase();
// or
let s_lowercase = ss.to_lowercase();
1. 文字列スライス str
を文字列 String
に変換する 16 つの方法
let ss: &str = "str";
let s: String = ss.to_string();
// or
let s: String = String::from(ss);
// or
let s: String = ss.into();
// or
let s: String = ss.to_owned();
// or
use std::convert::TryFrom;
let s: String = String::try_from(ss).unwrap();
// or
use std::convert::TryInto;
let s: String = ss.try_into().unwrap();
// or
use std::str::FromStr;
let s: String = String::from_str(ss).unwrap();
// or
let s: String = ss.parse().unwrap();
// or
let s: String = String::from_utf8(ss.as_bytes().to_owned()).unwrap();
// 文字列置換を伴う型変換
let s_replaced: String = ss.replace("str", "String");
// or
let s_replaced: String = ss.replacen("str", "String", 1);
// 繰り返しを伴う型変換
let s_repeated: String = ss.repeat(3);
// 大文字・小文字変換を伴う型変換
let s_ascii_lowercase: String = ss.to_ascii_lowercase();
// or
let s_ascii_uppercase: String = ss.to_ascii_uppercase();
// or
let s_uppercase: String = ss.to_uppercase();
// or
let s_lowercase: String = ss.to_lowercase();
※説明のために変数全てで型指定をしていますが、型指定を省略できるものもあります。
1.1. UTF-8 バイト列から文字列 String
に変換
str
型から変換する前に、まずは UTF-8 バイト列からの変換を確認します。
※ to_owned
メソッドについては後述。
let ss: &str = "str";
let bytes: &[u8] = ss.as_bytes();
let bytes_owned: Vec<u8> = bytes.to_owned(); // &[u8] -> Vec<u8>
let s: String = String::from_utf8(bytes_owned).unwrap(); // Vec<u8> -> String
参考「from_utf8 - String in std::string - Rust」
1.2. to_owned
メソッドで借用データを異なる型で複製し所有する
Rust における to_owned
は clone
(クローン、複製する) を一般化した概念で、clone
では &Self
型から Self
型の複製を生成するのに対し、to_owned
は &Self
型から Self::Owned
型の複製を生成します。
借用したデータをそのまま所有することはできないので、複製して所有します。
参考「ToOwned in std::borrow - Rust」
let ss: &str = "str";
let s: String = ss.to_owned();
str
型における ToOwned
トレイトの実装は以下のようになっています。
impl ToOwned for str {
type Owned = String;
#[inline]
fn to_owned(&self) -> String {
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
}
// ...
}
from_utf8_unchecked
関数は from_utf8
関数の安全でない版で、正しい UTF-8 バイト列かどうかを確認せずに文字列 String
に変換します。
参考「from_utf8_unchecked - String in std::string - Rust」
&[u8]
から Vec<u8>
に型変換し所有するところでも to_owned
メソッドを使用します。
1.3. String::from
メソッドは str::to_owned
メソッドを呼ぶ
let ss: &str = "str";
let s: String = String::from(ss);
String
型は From
トレイトを実装し、本記事で使用している String::from
メソッドの定義は以下の通りです。
impl From<&str> for String {
// ...
#[inline]
fn from(s: &str) -> String {
s.to_owned()
}
}
参考「From<&'_ str> - String in std::string - Rust」
1.4. String::from
メソッドを呼ぶメソッド
let ss: &str = "str";
let s: String = ss.into();
// or
let s: String = ss.to_string();
From
トレイトを実装する型があるとき、その逆の特性である Into
トレイトが自動で実装されます。
これにより、from
と into
で逆の変換ができます。
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}
&str
型は Into
トレイトをブランケット実装します。
impl Into<String> for &str {
fn into(self) -> String {
String::from(self)
}
}
参考「Into<U> - Into in std::convert - Rust」
str
型の to_string
メソッドでは String::from
メソッドを呼びます。
impl ToString for str {
#[inline]
fn to_string(&self) -> String {
String::from(self)
}
}
1.5. try_from
メソッドと try_into
メソッド
from
/ into
で型変換ができるということは、失敗する可能性のある型変換 try_from
/ try_into
で型変換を試みて必ず成功するという特性を持つと考えられます。
let ss: &str = "str";
use std::convert::TryFrom;
let s: String = String::try_from(ss).unwrap();
// or
use std::convert::TryInto;
let s: String = ss.try_into().unwrap();
実際に、TryFrom
トレイトと TryInto
トレイトは以下のようにブランケット実装されます。
impl<T, U> TryFrom<U> for T
where
U: Into<T>,
{
type Error = Infallible;
fn try_from(value: U) -> Result<Self, Self::Error> {
Ok(U::into(value))
}
}
impl TryFrom<&str> for String {
type Error = Infallible;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Ok(<&str>::into(value))
}
}
参考「TryFrom<U> - String in std::string - Rust」
impl<T, U> TryInto<U> for T
where
U: TryFrom<T>,
{
type Error = U::Error;
fn try_into(self) -> Result<U, U::Error> {
U::try_from(self)
}
}
impl TryInto<String> for &str {
type Error = String::Error;
fn try_into(self) -> Result<String, String::Error> {
String::try_from(self)
}
}
参考「TryInto in std::convert - Rust」
1.6. from_str
メソッドと parse
メソッド
from_str
/ parse
は文字列スライス str
との変換に特化した from
/ into
のような機能です。
let ss: &str = "str";
use std::str::FromStr;
let s: String = String::from_str(ss).unwrap();
// or
let s: String = ss.parse().unwrap();
String
型は FromStr
トレイトを実装します。
impl FromStr for String {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<String, Self::Err> {
Ok(String::from(s))
}
}
参考「FromStr - String in std::string - Rust」
str::parse
メソッドは文字列 str
型から FromStr
トレイトを実装する型に変換します。
impl str {
// ...
pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
FromStr::from_str(self)
}
// ...
}
1.7. 文字列操作が目的の変換
Rust における文字列操作は String
型同士でも行えますが、文字列スライス str
から直接文字列操作をするメソッドがあります。
let ss: &str = "str";
// 文字列置換を伴う型変換
let s_replaced: String = ss.replace("str", "String");
// or
let s_replaced: String = ss.replacen("str", "String", 1);
// 繰り返しを伴う型変換
let s_repeated: String = ss.repeat(3);
// 大文字・小文字変換を伴う型変換
let s_ascii_lowercase: String = ss.to_ascii_lowercase();
// or
let s_ascii_uppercase: String = ss.to_ascii_uppercase();
// or
let s_uppercase: String = ss.to_uppercase();
// or
let s_lowercase: String = ss.to_lowercase();
参考「str - Rust」