Moveには文字列を表現するための組み込み型はありませんが、標準ライブラリには文字列のための2つの標準実装があります。std::stringモジュールはUTF-8エンコードされた文字列のためのString型とメソッドを定義し、2つ目のモジュールstd::asciiはASCII文字列型とそのメソッドを提供します。

Sui実行環境は、トランザクション入力でバイトベクトルを自動的にStringに変換します。そのため、多くの場合、トランザクションブロック内でStringを構築する必要はありません。

文字列はバイトです

どちらの種類の文字列を使用する場合でも、文字列は単なるバイトの集まりであることを理解しておくことが重要です。stringモジュールとasciiモジュールが提供するラッパーは、文字通りラッパー(包み紙)に過ぎません。これらは確かに安全性チェックや文字列操作のためのメソッドを提供しますが、結局のところ、それらは単なるバイトのベクトルなのです。

module book::custom_string {
    /// 誰でもベクトルをラップすることでカスタムの文字列のような型を実装できます。
    public struct MyString {
        bytes: vector<u8>,
    }

    /// バイトのベクトルを文字列に変換する`from_bytes`関数を実装します。
    public fun from_bytes(bytes: vector<u8>): MyString {
        MyString { bytes }
    }

    /// 文字列をバイトのベクトルに変換する`bytes`関数を実装します。
    public fun bytes(self: &MyString): &vector<u8> {
        &self.bytes
    }
}

UTF-8文字列の操作

標準ライブラリには2種類の文字列がありますが、Stringモジュールがデフォルトとして考えられるべきです。多くの一般的な操作のネイティブ実装があり、したがってMoveで完全に実装されているasciiモジュールよりも効率的です。

定義

std::stringモジュールのString型は次のように定義されています:

// File: move-stdlib/sources/string.move
/// `String`はutf8形式であることが保証されているバイトのシーケンスを保持します。
public struct String has copy, drop, store {
    bytes: vector<u8>,
}

文字列の作成

新しいUTF-8 Stringインスタンスを作成するには、string::utf8メソッドを使用できます。標準ライブラリは便宜上、vector<u8>.to_string()エイリアスを提供しています。

// モジュールは`std::string`で、型は`String`です
use std::string::{Self, String};

// 文字列は通常`utf8`関数を使用して作成されます
// 型宣言は必要ありませんが、ここでは明確にするために記載しています
let hello: String = string::utf8(b"Hello");

// `vector<u8>`の`.to_string()`エイリアスの方が便利です
let hello = b"Hello".to_string();

一般的な操作

UTF8文字列は文字列を操作するための多くのメソッドを提供します。文字列に対する最も一般的な操作は、連結、スライス、長さの取得です。さらに、カスタム文字列操作のために、bytes()メソッドを使用して基礎となるバイトベクトルを取得できます。

let mut str = b"Hello,".to_string();
let another = b" World!".to_string();

// append(String)は文字列の末尾にコンテンツを追加します
str.append(another);

// `sub_string(start, end)`は文字列のスライスをコピーします
str.sub_string(0, 5); // "Hello"

// `length()`は文字列のバイト数を返します
str.length(); // 12 (バイト)

// メソッドはチェーンすることもできます!部分文字列の長さを取得
str.sub_string(0, 5).length(); // 5 (バイト)

// 文字列が空かどうか
str.is_empty(); // false

// カスタム操作のために基礎となるバイトベクトルを取得
let bytes: &vector<u8> = str.bytes();

安全なUTF-8操作

デフォルトのutf8メソッドは、渡されたバイトが有効なUTF-8でない場合に中断する可能性があります。渡すバイトが有効であることが確実でない場合は、代わりにtry_utf8メソッドを使用する必要があります。これはOption<String>を返し、バイトが有効なUTF-8でない場合は値を含まず、それ以外の場合は文字列を含みます。

ヒント:try_*で始まる名前は、関数が期待される結果を含むOptionを返すか、操作が失敗した場合はnoneを返すことを示します。これはRustから借用した一般的な命名規則です。

// これは有効なUTF-8文字列です
let hello = b"Hello".try_to_string();

assert!(hello.is_some(), 0); // 値が有効なUTF-8でない場合に中断

// これは有効なUTF-8文字列ではありません
let invalid = b"\\xFF".try_to_string();

assert!(invalid.is_none(), 0); // 値が有効なUTF-8の場合に中断