字符串
虽然 Move 没有内置的字符串类型,但它在标准库中提供了两种字符串的标准实现。std::string
模块定义了一个 String
类型和处理 UTF-8 编码字符串的方法,而第二个模块 std::ascii
则提供了 ASCII String
类型及其方法。
Sui 执行环境会自动将字节向量转换为事务输入中的
String
。因此,在许多情况下,不需要在事务块中构造字符串。
字符串即字节
无论使用哪种类型的字符串,重要的是要知道字符串只是字节。string
和 ascii
模块提供的封装只是封装而已。它们提供了安全检查和与字符串相关的方法,但归根结底,它们只是字节的向量。
module book::custom_string {
/// Anyone can implement a custom string-like type by wrapping a vector.
public struct MyString {
bytes: vector<u8>,
}
/// Implement a `from_bytes` function to convert a vector of bytes to a string.
public fun from_bytes(bytes: vector<u8>): MyString {
MyString { bytes }
}
/// Implement a `bytes` function to convert a string to a vector of bytes.
public fun bytes(self: &MyString): &vector<u8> {
&self.bytes
}
}
使用 UTF-8 字符串
虽然标准库中有两种类型的字符串,但应该将 string
模块视为默认选项。它具有许多常见操作的本地实现,因此比完全在 Move 中实现的 ascii
模块更高效。
定义
std::string
模块中的 String
类型定义如下:
// 文件: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()
。
// the module is `std::string` and the type is `String`
use std::string::{Self, String};
// strings are normally created using the `utf8` function
// type declaration is not necessary, we put it here for clarity
let hello: String = string::utf8(b"Hello");
// The `.to_string()` alias on the `vector<u8>` is more convenient
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 借用的常见命名约定。
// this is a valid UTF-8 string
let hello = b"Hello".try_to_string();
assert!(hello.is_some(), 0); // abort if the value is not valid UTF-8
// this is not a valid UTF-8 string
let invalid = b"\xFF".try_to_string();
assert!(invalid.is_none(), 0); // abort if the value is valid UTF-8
UTF-8 的限制
string
模块没有提供一种访问字符串中单个字符的方法。这是因为 UTF-8 是一种可变长度编码,并且一个字符的长度可以从 1 到 4 个字节不等。类似地,length()
方法返回的是字符串的字节数,而不是字符数。
然而,sub_string
和 insert
等方法会检查字符边界,并在索引位于字符中间时中止。
ASCII 字符串
本节内容即将推出!