Структура String
Описание
UTF-8 кодированная, расширяемая строка.
String - это наиболее распространенный тип строк. Он владеет содержимым строки, которое хранится в буфере, выделенном в куче (см. раздел "Представление"). Он тесно связан со своим заимствованным аналогом - примитивным типом str.
Примеры
Вы можете создать String из строкового литерала с помощью String::from:
#![allow(unused)] fn main() { let hello = String::from("Hello, world!"); }
Вы можете добавить символ (char) к String с помощью метода push, и добавить &str с помощью метода push_str:
#![allow(unused)] fn main() { let mut hello = String::from("Hello, "); hello.push('w'); hello.push_str("orld!"); }
Если у вас есть вектор UTF-8 байт, вы можете создать из него String с помощью метода from_utf8:
#![allow(unused)] fn main() { // некоторые байты в векторе let sparkle_heart = vec![240, 159, 146, 150]; // Мы знаем, что эти байты валидны, поэтому используем `unwrap()`. let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); assert_eq!("💖", sparkle_heart); }
UTF-8
Строки всегда являются валидными UTF-8. Если вам нужна не-UTF-8 строка, рассмотрите OsString. Он похож, но без ограничения UTF-8. Поскольку UTF-8 является кодировкой переменной ширины, String обычно меньше массива тех же char:
#![allow(unused)] fn main() { // `s` - это ASCII, который представляет каждый `char` как один байт let s = "hello"; assert_eq!(s.len(), 5); // Массив `char` с тем же содержимым был бы длиннее, потому что // каждый `char` занимает четыре байта let s = ['h', 'e', 'l', 'l', 'o']; let size: usize = s.into_iter().map(|c| std::mem::size_of_val(&c)).sum(); assert_eq!(size, 20); // Однако для не-ASCII строк разница будет меньше // и иногда они одинаковы let s = "💖💖💖💖💖"; assert_eq!(s.len(), 20); let s = ['💖', '💖', '💖', '💖', '💖']; let size: usize = s.into_iter().map(|c| std::mem::size_of_val(&c)).sum(); assert_eq!(size, 20); }
Это поднимает интересные вопросы о том, как должна работать s[i]. Что должно быть i здесь? Несколько вариантов включают байтовые индексы и символьные индексы, но из-за кодировки UTF-8 только байтовые индексы обеспечивали бы постоянное время индексации. Получение i-го символа, например, доступно с помощью chars:
#![allow(unused)] fn main() { let s = "hello"; let third_character = s.chars().nth(2); assert_eq!(third_character, Some('l')); let s = "💖💖💖💖💖"; let third_character = s.chars().nth(2); assert_eq!(third_character, Some('💖')); }
Далее, что должна возвращать s[i]? Поскольку индексация возвращает ссылку на базовые данные, это может быть &u8, &[u8] или что-то подобное. Поскольку мы предоставляем только один индекс, &u8 имеет наибольший смысл, но это может быть не то, что ожидает пользователь, и этого можно явно достичь с помощью as_bytes():
#![allow(unused)] fn main() { // Первый байт - 104 - байтовое значение `'h'` let s = "hello"; assert_eq!(s.as_bytes()[0], 104); // или assert_eq!(s.as_bytes()[0], b'h'); // Первый байт - 240, что не очевидно полезно let s = "💖💖💖💖💖"; assert_eq!(s.as_bytes()[0], 240); }
Из-за этих неоднозначностей/ограничений индексация с помощью usize просто запрещена:
ⓘ
#![allow(unused)] fn main() { let s = "hello"; // Следующее не скомпилируется! println!("The first letter of s is {}", s[0]); }
Однако более понятно, как должна работать &s[i..j] (то есть индексация с диапазоном). Она должна принимать байтовые индексы (для постоянного времени) и возвращать &str, который закодирован в UTF-8. Это также называется "срез строки". Обратите внимание, что это вызовет панику, если предоставленные байтовые индексы не являются границами символов - см. is_char_boundary для более подробной информации. См. реализации для SliceIndex<str> для более подробной информации о срезах строк. Для версии среза строк без паники см. get.
Методы bytes и chars возвращают итераторы по байтам и кодовым точкам строки соответственно. Для итерации по кодовым точкам вместе с байтовыми индексами используйте char_indices.
Deref
String реализует Deref<Target = str>, и поэтому наследует все методы str. Кроме того, это означает, что вы можете передать String в функцию, которая принимает &str, используя амперсанд (&):
#![allow(unused)] fn main() { fn takes_str(s: &str) { } let s = String::from("Hello"); takes_str(&s); }
Это создаст &str из String и передаст его. Это преобразование очень дешевое, и поэтому, как правило, функции будут принимать &str в качестве аргументов, если им не нужна String по какой-то конкретной причине.
В некоторых случаях Rust не имеет достаточно информации, чтобы сделать это преобразование, известное как Deref coercion. В следующем примере срез строки &'a str реализует трейт TraitExample, и функция example_func принимает все, что реализует этот трейт. В этом случае Rust потребовалось бы сделать два неявных преобразования, которые Rust не может сделать. По этой причине следующий пример не скомпилируется.
ⓘ
#![allow(unused)] fn main() { trait TraitExample {} impl<'a> TraitExample for &'a str {} fn example_func<A: TraitExample>(example_arg: A) {} let example_string = String::from("example_string"); example_func(&example_string); }
Есть два варианта, которые сработают вместо этого. Первый - изменить строку example_func(&example_string); на example_func(example_string.as_str());, используя метод as_str() для явного извлечения среза строки, содержащего строку. Второй способ изменяет example_func(&example_string); на example_func(&*example_string);. В этом случае мы разыменовываем String в str, затем ссылаемся на str обратно в &str. Второй способ более идиоматичен, однако оба работают для явного выполнения преобразования, а не для reliance на неявное преобразование.
Представление
String состоит из трех компонентов: указателя на некоторые байты, длины и емкости. Указатель указывает на внутренний буфер, который String использует для хранения своих данных. Длина - это количество байтов, currently хранящихся в буфере, а емкость - это размер буфера в байтах. Таким образом, длина всегда будет меньше или равна емкости.
Этот буфер всегда хранится в куче.
Вы можете посмотреть на них с помощью методов as_ptr, len и capacity:
#![allow(unused)] fn main() { let story = String::from("Once upon a time..."); // Разбираем String на части. let (ptr, len, capacity) = story.into_raw_parts(); // story имеет девятнадцать байт assert_eq!(19, len); // Мы можем пересобрать String из ptr, len и capacity. Это все // небезопасно, потому что мы отвечаем за то, чтобы компоненты были // валидны: let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ; assert_eq!(String::from("Once upon a time..."), s); }
Если String имеет достаточную емкость, добавление элементов в него не приведет к перераспределению. Например, рассмотрим эту программу:
#![allow(unused)] fn main() { let mut s = String::new(); println!("{}", s.capacity()); for _ in 0..5 { s.push_str("hello"); println!("{}", s.capacity()); } }
Это выведет следующее:
0
8
16
16
32
32
Сначала у нас вообще нет выделенной памяти, но по мере добавления к строке она соответствующим образом увеличивает свою емкость. Если вместо этого мы используем метод with_capacity для выделения правильной емкости изначально:
#![allow(unused)] fn main() { let mut s = String::with_capacity(25); println!("{}", s.capacity()); for _ in 0..5 { s.push_str("hello"); println!("{}", s.capacity()); } }
Мы получаем другой вывод:
25
25
25
25
25
25
Здесь нет необходимости выделять больше памяти внутри цикла.
Сводная таблица методов структуры String
Создание и преобразование
| Метод | Версия | Описание | Пример |
|---|---|---|---|
new() | 1.0.0 | Создает пустую строку | String::new() |
with_capacity(capacity) | 1.0.0 | Создает строку с начальной емкостью | String::with_capacity(100) |
from_utf8(vec) | 1.0.0 | Создает из вектора байт | String::from_utf8(bytes) |
from_utf8_lossy(v) | 1.0.0 | Создает из байт с заменой невалидных символов | String::from_utf8_lossy(b"hello\xFF") |
from_utf16(v) | 1.0.0 | Создает из UTF-16 данных | String::from_utf16(utf16_data) |
from_utf16_lossy(v) | 1.0.0 | Создает из UTF-16 с заменой невалидных символов | String::from_utf16_lossy(utf16_data) |
from_raw_parts(buf, len, cap) ⚠️ | 1.0.0 | Создает из сырых компонентов | unsafe { String::from_raw_parts(ptr, len, cap) } |
from_utf8_unchecked(bytes) ⚠️ | 1.0.0 | Создает без проверки UTF-8 | unsafe { String::from_utf8_unchecked(bytes) } |
Основные операции
| Метод | Версия | Описание | Пример |
|---|---|---|---|
push(ch) | 1.0.0 | Добавляет символ | s.push('!') |
push_str(string) | 1.0.0 | Добавляет строку | s.push_str(" world") |
pop() | 1.0.0 | Удаляет и возвращает последний символ | s.pop() |
remove(idx) | 1.0.0 | Удаляет символ по индексу | s.remove(0) |
insert(idx, ch) | 1.0.0 | Вставляет символ по индексу | s.insert(0, '!') |
insert_str(idx, string) | 1.16.0 | Вставляет строку по индексу | s.insert_str(0, "Hello ") |
clear() | 1.0.0 | Очищает содержимое | s.clear() |
truncate(new_len) | 1.0.0 | Укорачивает до указанной длины | s.truncate(5) |
split_off(at) | 1.16.0 | Разделяет строку на две | let end = s.split_off(5) |
Получение информации
| Метод | Версия | Описание | Пример |
|---|---|---|---|
len() | 1.0.0 | Длина в байтах | s.len() |
is_empty() | 1.0.0 | Проверка на пустоту | s.is_empty() |
capacity() | 1.0.0 | Текущая емкость | s.capacity() |
as_str() | 1.7.0 | Возвращает &str | s.as_str() |
as_mut_str() | 1.7.0 | Возвращает &mut str | s.as_mut_str() |
as_bytes() | 1.0.0 | Возвращает &[u8] | s.as_bytes() |
as_mut_vec() ⚠️ | 1.0.0 | Возвращает &mut Vec | unsafe { s.as_mut_vec() } |
Управление памятью
| Метод | Версия | Описание | Пример |
|---|---|---|---|
reserve(additional) | 1.0.0 | Резервирует дополнительную емкость | s.reserve(100) |
reserve_exact(additional) | 1.0.0 | Резервирует точную дополнительную емкость | s.reserve_exact(100) |
try_reserve(additional) | 1.57.0 | Пытается резервировать емкость | s.try_reserve(100)? |
try_reserve_exact(additional) | 1.57.0 | Пытается резервировать точную емкость | s.try_reserve_exact(100)? |
shrink_to_fit() | 1.0.0 | Сжимает до минимальной емкости | s.shrink_to_fit() |
shrink_to(min_capacity) | 1.56.0 | Сжимает до указанной емкости | s.shrink_to(10) |
Преобразования и извлечения
| Метод | Версия | Описание | Пример |
|---|---|---|---|
into_bytes() | 1.0.0 | Преобразует в Vec | let bytes = s.into_bytes() |
into_boxed_str() | 1.4.0 | Преобразует в Box | let boxed = s.into_boxed_str() |
leak() | 1.72.0 | Преобразует в &'static mut str | let static_str = s.leak() |
into_raw_parts() | 1.93.0 | Разбирает на сырые компоненты | let (ptr, len, cap) = s.into_raw_parts() |
Поиск и замена
| Метод | Версия | Описание | Пример |
|---|---|---|---|
replace_range(range, with) | 1.27.0 | Заменяет диапазон | s.replace_range(0..5, "Hello") |
retain(predicate) | 1.26.0 | Сохраняет только символы по условию | `s.retain( |
extend_from_within(range) | 1.87.0 | Копирует диапазон в конец | s.extend_from_within(0..5) |
Экспериментальные методы ⚡️
| Метод | Описание | Пример |
|---|---|---|
try_with_capacity(capacity) | Создает с емкостью с обработкой ошибок | String::try_with_capacity(100)? |
from_utf8_lossy_owned(v) | Создает из Vec | String::from_utf8_lossy_owned(bytes) |
from_utf16le(v) | Создает из UTF-16LE | String::from_utf16le(le_data) |
from_utf16be(v) | Создает из UTF-16BE | String::from_utf16be(be_data) |
remove_matches(pat) | Удаляет все совпадения шаблона | s.remove_matches("foo") |
into_chars() | Преобразует в итератор по символам | let chars = s.into_chars() |
replace_first(from, to) | Заменяет первое вхождение на месте | s.replace_first("old", "new") |
replace_last(from, to) | Заменяет последнее вхождение на месте | s.replace_last("old", "new") |
Итераторы
| Метод | Версия | Описание | Пример |
|---|---|---|---|
drain(range) | 1.6.0 | Итератор по удаляемому диапазону | for c in s.drain(0..5) |
chars() | 1.0.0 | Итератор по символам | for c in s.chars() |
char_indices() | 1.0.0 | Итератор по символам с индексами | for (i, c) in s.char_indices() |
bytes() | 1.0.0 | Итератор по байтам | for b in s.bytes() |
Условные обозначения
- ⚠️ - Небезопасный метод (требует
unsafe) - ⚡️ - Экспериментальный метод (только в ночных сборках)
- Константные методы отмечены как
(const: версия)
Ключевые категории методов
Создание
- Конструкторы (
new,with_capacity) - Преобразования из других типов
- Небезопасное создание
Модификация
- Добавление (
push,push_str,insert) - Удаление (
pop,remove,truncate) - Замена (
replace_range,retain)
Управление памятью
- Резервирование (
reserve,try_reserve) - Сжатие (
shrink_to_fit,shrink_to)
Преобразования
- В другие строковые типы
- В байтовые представления
- В итераторы
Информация
- Размер и емкость
- Представления (
as_str,as_bytes)
Методы
new
#![allow(unused)] fn main() { pub const fn new() -> String }
Создает новую пустую String.
Учитывая, что String пуста, это не выделит никакого начального буфера. Хотя это означает, что эта начальная операция очень дешевая, это может вызвать чрезмерное выделение позже, когда вы добавите данные. Если у вас есть представление о том, сколько данных будет содержать String, рассмотрите метод with_capacity, чтобы предотвратить чрезмерное перераспределение.
Доступность: 1.0.0 (const: 1.39.0)
Примеры
#![allow(unused)] fn main() { let s = String::new(); }
with_capacity
#![allow(unused)] fn main() { pub fn with_capacity(capacity: usize) -> String }
Создает новую пустую String с как минимум указанной емкостью.
Строки имеют внутренний буфер для хранения своих данных. Емкость - это длина этого буфера, и ее можно запросить с помощью метода capacity. Этот метод создает пустую String, но с начальным буфером, который может содержать как минимум capacity байт. Это полезно, когда вы можете добавлять кучу данных в String, уменьшая количество перераспределений, которые ей нужно сделать.
Если заданная емкость равна 0, выделения не произойдет, и этот метод идентичен методу new.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::with_capacity(10); // String не содержит символов, даже though у нее есть емкость для большего assert_eq!(s.len(), 0); // Все это делается без перераспределения... let cap = s.capacity(); for _ in 0..10 { s.push('a'); } assert_eq!(s.capacity(), cap); // ...но это может заставить строку перераспределиться s.push('a'); }
try_with_capacity ⚡️
#![allow(unused)] fn main() { pub fn try_with_capacity(capacity: usize) -> Result<String, TryReserveError> }
Создает новую пустую String с как минимум указанной емкостью.
Доступность: Экспериментальный API (только в ночных сборках)
Ошибки
Возвращает Err, если емкость превышает isize::MAX байт, или если аллокатор памяти сообщает о сбое.
from_utf8
#![allow(unused)] fn main() { pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> }
Преобразует вектор байт в String.
Строка (String) состоит из байт (u8), и вектор байт (Vec<u8>) состоит из байт, поэтому эта функция преобразует между ними. Однако не все срезы байт являются валидными String: String требует, чтобы она была валидной UTF-8. from_utf8() проверяет, чтобы байты были валидными UTF-8, а затем выполняет преобразование.
Если вы уверены, что срез байт является валидным UTF-8, и вы не хотите нести накладные расходы проверки валидности, существует небезопасная версия этой функции, from_utf8_unchecked, которая имеет то же поведение, но пропускает проверку.
Этот метод позаботится о том, чтобы не копировать вектор, ради эффективности.
Если вам нужен &str вместо String, рассмотрите str::from_utf8.
Обратным методом этого является into_bytes.
Доступность: 1.0.0
Ошибки
Возвращает Err, если срез не является UTF-8 с описанием, почему предоставленные байты не являются UTF-8. Вектор, который вы переместили, также включен.
Примеры
Базовое использование:
#![allow(unused)] fn main() { // некоторые байты в векторе let sparkle_heart = vec![240, 159, 146, 150]; // Мы знаем, что эти байты валидны, поэтому используем `unwrap()`. let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); assert_eq!("💖", sparkle_heart); }
Неправильные байты:
#![allow(unused)] fn main() { // некоторые невалидные байты в векторе let sparkle_heart = vec![0, 159, 146, 150]; assert!(String::from_utf8(sparkle_heart).is_err()); }
Смотрите документацию для FromUtf8Error для более подробной информации о том, что вы можете сделать с этой ошибкой.
from_utf8_lossy
#![allow(unused)] fn main() { pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> }
Преобразует срез байт в строку, включая невалидные символы.
Строки состоят из байт (u8), и срез байт (&[u8]) состоит из байт, поэтому эта функция преобразует между ними. Однако не все срезы байт являются валидными строками: строки должны быть валидными UTF-8. Во время этого преобразования from_utf8_lossy() заменит любые невалидные UTF-8 последовательности на U+FFFD REPLACEMENT CHARACTER, который выглядит так: �
Если вы уверены, что срез байт является валидным UTF-8, и вы не хотите нести накладные расходы преобразования, существует небезопасная версия этой функции, from_utf8_unchecked, которая имеет то же поведение, но пропускает проверки.
Эта функция возвращает Cow<'a, str>. Если наш срез байт является невалидным UTF-8, то нам нужно вставить символы замены, что изменит размер строки и, следовательно, потребует String. Но если он уже является валидным UTF-8, нам не нужно новое выделение. Этот тип возврата позволяет нам обрабатывать оба случая.
Доступность: 1.0.0
Примеры
Базовое использование:
#![allow(unused)] fn main() { // некоторые байты в векторе let sparkle_heart = vec![240, 159, 146, 150]; let sparkle_heart = String::from_utf8_lossy(&sparkle_heart); assert_eq!("💖", sparkle_heart); }
Неправильные байты:
#![allow(unused)] fn main() { // некоторые невалидные байты let input = b"Hello \xF0\x90\x80World"; let output = String::from_utf8_lossy(input); assert_eq!("Hello �World", output); }
from_utf8_lossy_owned ⚡️
#![allow(unused)] fn main() { pub fn from_utf8_lossy_owned(v: Vec<u8>) -> String }
Преобразует Vec<u8> в String, заменяя невалидные UTF-8 последовательности символами замены.
Смотрите from_utf8_lossy для более подробной информации.
Обратите внимание, что эта функция не гарантирует повторное использование исходного выделения Vec.
Доступность: Экспериментальный API (только в ночных сборках)
Примеры
Базовое использование:
#![allow(unused)] #![feature(string_from_utf8_lossy_owned)] fn main() { // некоторые байты в векторе let sparkle_heart = vec![240, 159, 146, 150]; let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart); assert_eq!(String::from("💖"), sparkle_heart); }
Неправильные байты:
#![allow(unused)] #![feature(string_from_utf8_lossy_owned)] fn main() { // некоторые невалидные байты let input: Vec<u8> = b"Hello \xF0\x90\x80World".into(); let output = String::from_utf8_lossy_owned(input); assert_eq!(String::from("Hello �World"), output); }
from_utf16
#![allow(unused)] fn main() { pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> }
Декодирует вектор, закодированный в UTF-16 с родным порядком байт, в String, возвращая Err, если v содержит любые невалидные данные.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { // 𝄞music let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0x0069, 0x0063]; assert_eq!(String::from("𝄞music"), String::from_utf16(v).unwrap()); // 𝄞mu<invalid>ic let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; assert!(String::from_utf16(v).is_err()); }
from_utf16_lossy
#![allow(unused)] fn main() { pub fn from_utf16_lossy(v: &[u16]) -> String }
Декодирует срез, закодированный в UTF-16 с родным порядком байт, в String, заменяя невалидные данные символом замены (U+FFFD).
В отличие от from_utf8_lossy, который возвращает Cow<'a, str>, from_utf16_lossy возвращает String, поскольку преобразование из UTF-16 в UTF-8 требует выделения памяти.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { // 𝄞mus<invalid>ic<invalid> let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834]; assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), String::from_utf16_lossy(v)); }
from_utf16le ⚡️
#![allow(unused)] fn main() { pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> }
Декодирует вектор, закодированный в UTF-16LE, в String, возвращая Err, если v содержит любые невалидные данные.
Доступность: Экспериментальный API (только в ночных сборлах)
Примеры
Базовое использование:
#![allow(unused)] #![feature(str_from_utf16_endian)] fn main() { // 𝄞music let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00]; assert_eq!(String::from("𝄞music"), String::from_utf16le(v).unwrap()); // 𝄞mu<invalid>ic let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00]; assert!(String::from_utf16le(v).is_err()); }
from_utf16le_lossy ⚡️
#![allow(unused)] fn main() { pub fn from_utf16le_lossy(v: &[u8]) -> String }
Декодирует срез, закодированный в UTF-16LE, в String, заменяя невалидные данные символом замены (U+FFFD).
В отличие от from_utf8_lossy, который возвращает Cow<'a, str>, from_utf16le_lossy возвращает String, поскольку преобразование из UTF-16 в UTF-8 требует выделения памяти.
Доступность: Экспериментальный API (только в ночных сборлах)
Примеры
Базовое использование:
#![allow(unused)] #![feature(str_from_utf16_endian)] fn main() { // 𝄞mus<invalid>ic<invalid> let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00, 0x34, 0xD8]; assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), String::from_utf16le_lossy(v)); }
from_utf16be ⚡️
#![allow(unused)] fn main() { pub fn from_utf16be(v: &[u8]) -> Result<String, FromUtf16Error> }
Декодирует вектор, закодированный в UTF-16BE, в String, возвращая Err, если v содержит любые невалидные данные.
Доступность: Экспериментальный API (только в ночных сборлах)
Примеры
Базовое использование:
#![allow(unused)] #![feature(str_from_utf16_endian)] fn main() { // 𝄞music let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63]; assert_eq!(String::from("𝄞music"), String::from_utf16be(v).unwrap()); // 𝄞mu<invalid>ic let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63]; assert!(String::from_utf16be(v).is_err()); }
from_utf16be_lossy ⚡️
#![allow(unused)] fn main() { pub fn from_utf16be_lossy(v: &[u8]) -> String }
Декодирует срез, закодированный в UTF-16BE, в String, заменяя невалидные данные символом замены (U+FFFD).
В отличие от from_utf8_lossy, который возвращает Cow<'a, str>, from_utf16le_lossy возвращает String, поскольку преобразование из UTF-16 в UTF-8 требует выделения памяти.
Доступность: Экспериментальный API (только в ночных сборлах)
Примеры
Базовое использование:
#![allow(unused)] #![feature(str_from_utf16_endian)] fn main() { // 𝄞mus<invalid>ic<invalid> let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63, 0xD8, 0x34]; assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), String::from_utf16be_lossy(v)); }
into_raw_parts
#![allow(unused)] fn main() { pub fn into_raw_parts(self) -> (*mut u8, usize, usize) }
Разлагает String на его сырые компоненты: (указатель, длина, емкость).
Возвращает сырой указатель на базовые данные, длину строки (в байтах) и выделенную емкость данных (в байтах). Это те же аргументы в том же порядке, что и аргументы для from_raw_parts.
После вызова этой функции вызывающий отвечает за память, ранее управляемую String. Единственный способ сделать это - преобразовать сырой указатель, длину и емкость обратно в String с помощью функции from_raw_parts, позволяя деструктору выполнить очистку.
Доступность: 1.93.0
Примеры
#![allow(unused)] fn main() { let s = String::from("hello"); let (ptr, len, cap) = s.into_raw_parts(); let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; assert_eq!(rebuilt, "hello"); }
from_raw_parts ⚠️
#![allow(unused)] fn main() { pub unsafe fn from_raw_parts( buf: *mut u8, length: usize, capacity: usize, ) -> String }
Создает новую String из указателя, длины и емкости.
Безопасность
Это очень небезопасно из-за количества инвариантов, которые не проверяются:
- все требования безопасности для
Vec::<u8>::from_raw_parts - все требования безопасности для
String::from_utf8_unchecked
Нарушение этих требований может вызвать проблемы, такие как повреждение внутренних структур данных аллокатора. Например, обычно небезопасно строить String из указателя на массив C char, содержащий UTF-8, если вы не уверены, что этот массив был изначально выделен аллокатором стандартной библиотеки Rust.
Владение buf эффективно передается String, который затем может освободить, перераспределить или изменить содержимое памяти, на которую указывает указатель, по своему желанию. Убедитесь, что больше ничего не использует указатель после вызова этой функции.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { unsafe { let s = String::from("hello"); // Разбираем String на части. let (ptr, len, capacity) = s.into_raw_parts(); let s = String::from_raw_parts(ptr, len, capacity); assert_eq!(String::from("hello"), s); } }
from_utf8_unchecked ⚠️
#![allow(unused)] fn main() { pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String }
Преобразует вектор байт в String без проверки того, что строка содержит валидный UTF-8.
Смотрите безопасную версию, from_utf8, для более подробной информации.
Безопасность
Эта функция небезопасна, потому что она не проверяет, что байты, переданные ей, являются валидными UTF-8. Если это ограничение нарушено, это может вызвать проблемы с безопасностью памяти у будущих пользователей String, поскольку остальная часть стандартной библиотеки предполагает, что String являются валидными UTF-8.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { // некоторые байты в векторе let sparkle_heart = vec![240, 159, 146, 150]; let sparkle_heart = unsafe { String::from_utf8_unchecked(sparkle_heart) }; assert_eq!("💖", sparkle_heart); }
into_bytes
#![allow(unused)] fn main() { pub const fn into_bytes(self) -> Vec<u8> ⓘ }
Преобразует String в вектор байт.
Это потребляет String, поэтому нам не нужно копировать его содержимое.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let s = String::from("hello"); let bytes = s.into_bytes(); assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); }
as_str
#![allow(unused)] fn main() { pub const fn as_str(&self) -> &str }
Извлекает срез строки, содержащий всю String.
Доступность: 1.7.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let s = String::from("foo"); assert_eq!("foo", s.as_str()); }
as_mut_str
#![allow(unused)] fn main() { pub const fn as_mut_str(&mut self) -> &mut str }
Преобразует String в изменяемый срез строки.
Доступность: 1.7.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let mut s = String::from("foobar"); let s_mut_str = s.as_mut_str(); s_mut_str.make_ascii_uppercase(); assert_eq!("FOOBAR", s_mut_str); }
push_str
#![allow(unused)] fn main() { pub fn push_str(&mut self, string: &str) }
Добавляет заданный срез строки в конец этой String.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("foo"); s.push_str("bar"); assert_eq!("foobar", s); }
extend_from_within
#![allow(unused)] fn main() { pub fn extend_from_within<R>(&mut self, src: R) where R: RangeBounds<usize>, }
Копирует элементы из диапазона src в конец строки.
Доступность: 1.87.0
Паника
Паникует, если диапазон имеет start_bound > end_bound, или если диапазон ограничен с любого конца и не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut string = String::from("abcde"); string.extend_from_within(2..); assert_eq!(string, "abcdecde"); string.extend_from_within(..2); assert_eq!(string, "abcdecdeab"); string.extend_from_within(4..8); assert_eq!(string, "abcdecdeabecde"); }
capacity
#![allow(unused)] fn main() { pub const fn capacity(&self) -> usize }
Возвращает емкость этой String в байтах.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let s = String::with_capacity(10); assert!(s.capacity() >= 10); }
reserve
#![allow(unused)] fn main() { pub fn reserve(&mut self, additional: usize) }
Резервирует емкость для как минимум additional байт больше текущей длины. Аллокатор может зарезервировать больше места, чтобы спекулятивно избежать частых выделений. После вызова reserve емкость будет больше или равна self.len() + additional. Ничего не делает, если емкость уже достаточна.
Доступность: 1.0.0
Паника
Паникует, если новая емкость переполняет usize.
Примеры
Базовое использование:
#![allow(unused)] fn main() { let mut s = String::new(); s.reserve(10); assert!(s.capacity() >= 10); }
Это может фактически не увеличить емкость:
#![allow(unused)] fn main() { let mut s = String::with_capacity(10); s.push('a'); s.push('b'); // s теперь имеет длину 2 и емкость как минимум 10 let capacity = s.capacity(); assert_eq!(2, s.len()); assert!(capacity >= 10); // Поскольку у нас уже есть как минимум дополнительные 8 емкости, вызов этого... s.reserve(8); // ... фактически не увеличивает. assert_eq!(capacity, s.capacity()); }
reserve_exact
#![allow(unused)] fn main() { pub fn reserve_exact(&mut self, additional: usize) }
Резервирует минимальную емкость для как минимум additional байт больше текущей длины. В отличие от reserve, это не будет намеренно перераспределять, чтобы спекулятивно избежать частых выделений. После вызова reserve_exact емкость будет больше или равна self.len() + additional. Ничего не делает, если емкость уже достаточна.
Доступность: 1.0.0
Паника
Паникует, если новая емкость переполняет usize.
Примеры
Базовое использование:
#![allow(unused)] fn main() { let mut s = String::new(); s.reserve_exact(10); assert!(s.capacity() >= 10); }
Это может фактически не увеличить емкость:
#![allow(unused)] fn main() { let mut s = String::with_capacity(10); s.push('a'); s.push('b'); // s теперь имеет длину 2 и емкость как минимум 10 let capacity = s.capacity(); assert_eq!(2, s.len()); assert!(capacity >= 10); // Поскольку у нас уже есть как минимум дополнительные 8 емкости, вызов этого... s.reserve_exact(8); // ... фактически не увеличивает. assert_eq!(capacity, s.capacity()); }
try_reserve
#![allow(unused)] fn main() { pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> }
Пытается зарезервировать емкость для как минимум additional байт больше текущей длины. Аллокатор может зарезервировать больше места, чтобы спекулятивно избежать частых выделений. После вызова try_reserve емкость будет больше или равна self.len() + additional, если он возвращает Ok(()). Ничего не делает, если емкость уже достаточна. Этот метод сохраняет содержимое, даже если происходит ошибка.
Доступность: 1.57.0
Ошибки
Если емкость переполняется или аллокатор сообщает о сбое, то возвращается ошибка.
Примеры
#![allow(unused)] fn main() { use std::collections::TryReserveError; fn process_data(data: &str) -> Result<String, TryReserveError> { let mut output = String::new(); // Предварительно резервируем память, выходя если не можем output.try_reserve(data.len())?; // Теперь мы знаем, что это не может вызвать OOM в середине нашей сложной работы output.push_str(data); Ok(output) } }
try_reserve_exact
#![allow(unused)] fn main() { pub fn try_reserve_exact( &mut self, additional: usize, ) -> Result<(), TryReserveError> }
Пытается зарезервировать минимальную емкость для как минимум additional байт больше текущей длины. В отличие от try_reserve, это не будет намеренно перераспределять, чтобы спекулятивно избежать частых выделений. После вызова try_reserve_exact емкость будет больше или равна self.len() + additional, если он возвращает Ok(()). Ничего не делает, если емкость уже достаточна.
Обратите внимание, что аллокатор может дать коллекции больше места, чем она запрашивает. Поэтому на емкость нельзя полагаться как на точно минимальную. Предпочитайте try_reserve, если ожидаются будущие вставки.
Доступность: 1.57.0
Ошибки
Если емкость переполняется или аллокатор сообщает о сбое, то возвращается ошибка.
Примеры
#![allow(unused)] fn main() { use std::collections::TryReserveError; fn process_data(data: &str) -> Result<String, TryReserveError> { let mut output = String::new(); // Предварительно резервируем память, выходя если не можем output.try_reserve_exact(data.len())?; // Теперь мы знаем, что это не может вызвать OOM в середине нашей сложной работы output.push_str(data); Ok(output) } }
shrink_to_fit
#![allow(unused)] fn main() { pub fn shrink_to_fit(&mut self) }
Сжимает емкость этой String до match ее длины.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("foo"); s.reserve(100); assert!(s.capacity() >= 100); s.shrink_to_fit(); assert_eq!(3, s.capacity()); }
shrink_to
#![allow(unused)] fn main() { pub fn shrink_to(&mut self, min_capacity: usize) }
Сжимает емкость этой String с нижней границей.
Емкость останется как минимум такой же большой, как и длина, и supplied значение.
Если текущая емкость меньше нижнего предела, это не операция.
Доступность: 1.56.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("foo"); s.reserve(100); assert!(s.capacity() >= 100); s.shrink_to(10); assert!(s.capacity() >= 10); s.shrink_to(0); assert!(s.capacity() >= 3); }
push
#![allow(unused)] fn main() { pub fn push(&mut self, ch: char) }
Добавляет заданный char в конец этой String.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("abc"); s.push('1'); s.push('2'); s.push('3'); assert_eq!("abc123", s); }
as_bytes
#![allow(unused)] fn main() { pub const fn as_bytes(&self) -> &[u8] ⓘ }
Возвращает срез байт содержимого этой String.
Обратным методом этого является from_utf8.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let s = String::from("hello"); assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); }
truncate
#![allow(unused)] fn main() { pub fn truncate(&mut self, new_len: usize) }
Укорачивает эту String до указанной длины.
Если new_len больше или равна текущей длине строки, это не имеет эффекта.
Обратите внимание, что этот метод не влияет на выделенную емкость строки.
Доступность: 1.0.0
Паника
Паникует, если new_len не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut s = String::from("hello"); s.truncate(2); assert_eq!("he", s); }
pop
#![allow(unused)] fn main() { pub fn pop(&mut self) -> Option<char> }
Удаляет последний символ из строкового буфера и возвращает его.
Возвращает None, если эта String пуста.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("abč"); assert_eq!(s.pop(), Some('č')); assert_eq!(s.pop(), Some('b')); assert_eq!(s.pop(), Some('a')); assert_eq!(s.pop(), None); }
remove
#![allow(unused)] fn main() { pub fn remove(&mut self, idx: usize) -> char }
Удаляет char из этой String в байтовой позиции idx и возвращает его.
Копирует все байты после удаленного char в новые позиции.
Обратите внимание, что вызов этого в цикле может привести к квадратичному поведению.
Доступность: 1.0.0
Паника
Паникует, если idx больше или равна длине String, или если она не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut s = String::from("abç"); assert_eq!(s.remove(0), 'a'); assert_eq!(s.remove(1), 'ç'); assert_eq!(s.remove(0), 'b'); }
remove_matches ⚡️
#![allow(unused)] fn main() { pub fn remove_matches<P>(&mut self, pat: P) where P: Pattern, }
Удаляет все совпадения шаблона pat в String.
Доступность: Экспериментальный API (только в ночных сборках)
Примеры
#![allow(unused)] #![feature(string_remove_matches)] fn main() { let mut s = String::from("Trees are not green, the sky is not blue."); s.remove_matches("not "); assert_eq!("Trees are green, the sky is blue.", s); }
Совпадения будут обнаружены и удалены итеративно, поэтому в случаях, когда шаблоны перекрываются, будет удален только первый шаблон:
#![allow(unused)] #![feature(string_remove_matches)] fn main() { let mut s = String::from("banana"); s.remove_matches("ana"); assert_eq!("bna", s); }
retain
#![allow(unused)] fn main() { pub fn retain<F>(&mut self, f: F) where F: FnMut(char) -> bool, }
Сохраняет только символы, указанные предикатом.
Другими словами, удаляет все символы c такие, что f(c) возвращает false. Этот метод работает на месте, посещая каждый символ exactly один раз в исходном порядке, и сохраняет порядок сохраненных символов.
Доступность: 1.26.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("f_o_ob_ar"); s.retain(|c| c != '_'); assert_eq!(s, "foobar"); }
Поскольку элементы посещаются exactly один раз в исходном порядке, внешнее состояние может быть использовано для решения, какие элементы сохранить.
#![allow(unused)] fn main() { let mut s = String::from("abcde"); let keep = [false, true, true, false, true]; let mut iter = keep.iter(); s.retain(|_| *iter.next().unwrap()); assert_eq!(s, "bce"); }
insert
#![allow(unused)] fn main() { pub fn insert(&mut self, idx: usize, ch: char) }
Вставляет символ в эту String в байтовой позиции idx.
Перераспределяет, если self.capacity() недостаточна, что может включать копирование всех self.capacity() байт. Освобождает место для вставки, копируя все байты &self[idx..] в новые позиции.
Обратите внимание, что вызов этого в цикле может привести к квадратичному поведению.
Доступность: 1.0.0
Паника
Паникует, если idx больше длины String, или если она не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut s = String::with_capacity(3); s.insert(0, 'f'); s.insert(1, 'o'); s.insert(2, 'o'); assert_eq!("foo", s); }
insert_str
#![allow(unused)] fn main() { pub fn insert_str(&mut self, idx: usize, string: &str) }
Вставляет срез строки в эту String в байтовой позиции idx.
Перераспределяет, если self.capacity() недостаточна, что может включать копирование всех self.capacity() байт. Освобождает место для вставки, копируя все байты &self[idx..] в новые позиции.
Обратите внимание, что вызов этого в цикле может привести к квадратичному поведению.
Доступность: 1.16.0
Паника
Паникует, если idx больше длины String, или если она не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut s = String::from("bar"); s.insert_str(0, "foo"); assert_eq!("foobar", s); }
as_mut_vec ⚠️
#![allow(unused)] fn main() { pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> ⓘ }
Возвращает изменяемую ссылку на содержимое этой String.
Безопасность
Эта функция небезопасна, потому что возвращенный &mut Vec позволяет записывать байты, которые не являются валидными UTF-8. Если это ограничение нарушено, использование исходной String после удаления &mut Vec может нарушить безопасность памяти, поскольку остальная часть стандартной библиотеки предполагает, что String являются валидными UTF-8.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let mut s = String::from("hello"); unsafe { let vec = s.as_mut_vec(); assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); vec.reverse(); } assert_eq!(s, "olleh"); }
len
#![allow(unused)] fn main() { pub const fn len(&self) -> usize }
Возвращает длину этой String в байтах, не в символах или графемах. Другими словами, это может быть не то, что человек считает длиной строки.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let a = String::from("foo"); assert_eq!(a.len(), 3); let fancy_f = String::from("ƒoo"); assert_eq!(fancy_f.len(), 4); assert_eq!(fancy_f.chars().count(), 3); }
is_empty
#![allow(unused)] fn main() { pub const fn is_empty(&self) -> bool }
Возвращает true, если эта String имеет длину ноль, и false otherwise.
Доступность: 1.0.0 (const: 1.87.0)
Примеры
#![allow(unused)] fn main() { let mut v = String::new(); assert!(v.is_empty()); v.push('a'); assert!(!v.is_empty()); }
split_off
#![allow(unused)] fn main() { pub fn split_off(&mut self, at: usize) -> String }
Разделяет строку на две по заданному байтовому индексу.
Возвращает новую выделенную String. self содержит байты [0, at), а возвращенная String содержит байты [at, len). at должен быть на границе кодовой точки UTF-8.
Обратите внимание, что емкость self не меняется.
Доступность: 1.16.0
Паника
Паникует, если at не на границе кодовой точки UTF-8, или если он beyond последней кодовой точки строки.
Примеры
#![allow(unused)] fn main() { let mut hello = String::from("Hello, World!"); let world = hello.split_off(7); assert_eq!(hello, "Hello, "); assert_eq!(world, "World!"); }
clear
#![allow(unused)] fn main() { pub fn clear(&mut self) }
Усекает эту String, удаляя все содержимое.
Хотя это означает, что String будет иметь длину ноль, это не касается ее емкости.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("foo"); s.clear(); assert!(s.is_empty()); assert_eq!(0, s.len()); assert_eq!(3, s.capacity()); }
drain
#![allow(unused)] fn main() { pub fn drain<R>(&mut self, range: R) -> Drain<'_> ⓘ where R: RangeBounds<usize>, }
Удаляет указанный диапазон из строки bulk, возвращая все удаленные символы как итератор.
Возвращенный итератор сохраняет изменяемое заимствование строки для оптимизации своей реализации.
Доступность: 1.6.0
Паника
Паникует, если диапазон имеет start_bound > end_bound, или если диапазон ограничен с любого конца и не лежит на границе символа.
Утечка
Если возвращенный итератор выходит из области видимости без being dropped (из-за core::mem::forget, например), строка может все еще содержать копию любых drained символов, или может потерять символы arbitrarily, включая символы вне диапазона.
Примеры
#![allow(unused)] fn main() { let mut s = String::from("α is alpha, β is beta"); let beta_offset = s.find('β').unwrap_or(s.len()); // Удаляем диапазон до β из строки let t: String = s.drain(..beta_offset).collect(); assert_eq!(t, "α is alpha, "); assert_eq!(s, "β is beta"); // Полный диапазон очищает строку, как это делает `clear()` s.drain(..); assert_eq!(s, ""); }
into_chars ⚡️
#![allow(unused)] fn main() { pub fn into_chars(self) -> IntoChars ⓘ }
Преобразует String в итератор по символам строки.
Поскольку строка состоит из валидного UTF-8, мы можем итерироваться по строке по символам. Этот метод возвращает такой итератор.
Важно помнить, что char представляет Unicode Scalar Value и может не соответствовать вашему представлению о 'символе'. Итерация по кластерам графем может быть тем, что вам actually нужно. Эта функциональность не предоставляется стандартной библиотекой Rust, проверьте crates.io instead.
Доступность: Экспериментальный API (только в ночных сборках)
Примеры
Базовое использование:
#![allow(unused)] #![feature(string_into_chars)] fn main() { let word = String::from("goodbye"); let mut chars = word.into_chars(); assert_eq!(Some('g'), chars.next()); assert_eq!(Some('o'), chars.next()); assert_eq!(Some('o'), chars.next()); assert_eq!(Some('d'), chars.next()); assert_eq!(Some('b'), chars.next()); assert_eq!(Some('y'), chars.next()); assert_eq!(Some('e'), chars.next()); assert_eq!(None, chars.next()); }
Помните, chars может не соответствовать вашей интуиции о символах:
#![allow(unused)] #![feature(string_into_chars)] fn main() { let y = String::from("y̆"); let mut chars = y.into_chars(); assert_eq!(Some('y'), chars.next()); // не 'y̆' assert_eq!(Some('\u{0306}'), chars.next()); assert_eq!(None, chars.next()); }
replace_range
#![allow(unused)] fn main() { pub fn replace_range<R>(&mut self, range: R, replace_with: &str) where R: RangeBounds<usize>, }
Удаляет указанный диапазон в строке и заменяет его заданной строкой. Заданная строка не должна быть той же длины, что и диапазон.
Доступность: 1.27.0
Паника
Паникует, если диапазон имеет start_bound > end_bound, или если диапазон ограничен с любого конца и не лежит на границе символа.
Примеры
#![allow(unused)] fn main() { let mut s = String::from("α is alpha, β is beta"); let beta_offset = s.find('β').unwrap_or(s.len()); // Заменяем диапазон до β из строки s.replace_range(..beta_offset, "Α is capital alpha; "); assert_eq!(s, "Α is capital alpha; β is beta"); }
replace_first ⚡️
#![allow(unused)] fn main() { pub fn replace_first<P>(&mut self, from: P, to: &str) where P: Pattern, }
Заменяет самое левое вхождение шаблона другой строкой на месте.
Этот метод может быть предпочтительнее над string = string.replacen(..., 1);, так как он может использовать существующую емкость String для предотвращения перераспределения, если доступно достаточно места.
Доступность: Экспериментальный API (только в ночных сборках)
Примеры
Базовое использование:
#![allow(unused)] #![feature(string_replace_in_place)] fn main() { let mut s = String::from("Test Results: ❌❌❌"); // Заменяем самое левое ❌ на ✅ s.replace_first('❌', "✅"); assert_eq!(s, "Test Results: ✅❌❌"); }
replace_last ⚡️
#![allow(unused)] fn main() { pub fn replace_last<P>(&mut self, from: P, to: &str) where P: Pattern, <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>, }
Заменяет самое правое вхождение шаблона другой строкой на месте.
Доступность: Экспериментальный API (только в ночных сборлах)
Примеры
Базовое использование:
#![allow(unused)] #![feature(string_replace_in_place)] fn main() { let mut s = String::from("Test Results: ❌❌❌"); // Заменяем самое правое ❌ на ✅ s.replace_last('❌', "✅"); assert_eq!(s, "Test Results: ❌❌✅"); }
into_boxed_str
#![allow(unused)] fn main() { pub fn into_boxed_str(self) -> Box<str> }
Преобразует эту String в Box<str>.
Перед выполнением преобразования этот метод отбрасывает избыточную емкость как shrink_to_fit. Обратите внимание, что этот вызов может перераспределить и скопировать байты строки.
Доступность: 1.4.0
Примеры
#![allow(unused)] fn main() { let s = String::from("hello"); let b = s.into_boxed_str(); }
leak
#![allow(unused)] fn main() { pub fn leak<'a>(self) -> &'a mut str }
Потребляет и leaking String, возвращая изменяемую ссылку на содержимое, &'a mut str.
Вызывающий имеет свободный выбор над возвращенным временем жизни, включая 'static. Действительно, эта функция идеально используется для данных, которые живут в течение оставшейся жизни программы, так как удаление возвращенной ссылки вызовет утечку памяти.
Он не перераспределяет и не сжимает String, поэтому leaking выделение может включать неиспользуемую емкость, которая не является частью возвращенного среза. Если вы хотите отбросить избыточную емкость, вызовите into_boxed_str, а затем Box::leak instead. Однако имейте в виду, что обрезка емкости может привести к перераспределению и копированию.
Доступность: 1.72.0
Примеры
#![allow(unused)] fn main() { let x = String::from("bucket"); let static_ref: &'static mut str = x.leak(); assert_eq!(static_ref, "bucket"); }
Реализации трейтов
Add<&str> для String
Реализует оператор + для конкатенации двух строк.
Это потребляет String на левой стороне и повторно использует ее буфер (увеличивая его при необходимости). Это делается для того, чтобы избежать выделения новой String и копирования всего содержимого при каждой операции, что привело бы к времени выполнения O(n^2) при построении n-байтовой строки путем repeated конкатенации.
Строка на правой стороне только заимствуется; ее содержимое копируется в возвращенную String.
Доступность: 1.0.0
Примеры
Конкатенация двух String берет первую по значению и заимствует вторую:
#![allow(unused)] fn main() { let a = String::from("hello"); let b = String::from(" world"); let c = a + &b; // `a` перемещена и больше не может быть использована здесь. }
Если вы хотите продолжать использовать первую String, вы можете клонировать ее и добавить к клону instead:
#![allow(unused)] fn main() { let a = String::from("hello"); let b = String::from(" world"); let c = a.clone() + &b; // `a` все еще валидна здесь. }
Конкатенация срезов &str может быть выполнена путем преобразования первой в String:
#![allow(unused)] fn main() { let a = "hello"; let b = " world"; let c = a.to_string() + b; }
Ассоциированный тип
#![allow(unused)] fn main() { type Output = String }
Результирующий тип после применения оператора +.
Метод
#![allow(unused)] fn main() { fn add(self, other: &str) -> String }
Выполняет операцию +. Читать далее
AddAssign<&str> для String
Реализует оператор += для добавления к String.
Это имеет то же поведение, что и метод push_str.
Доступность: 1.12.0
Метод
#![allow(unused)] fn main() { fn add_assign(&mut self, other: &str) }
Выполняет операцию +=. Читать далее
AsMut<str> для String
Доступность: 1.43.0
Метод
#![allow(unused)] fn main() { fn as_mut(&mut self) -> &mut str }
Преобразует этот тип в изменяемую ссылку (обычно inferred) входного типа.
AsRef<[u8]> для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn as_ref(&self) -> &[u8] ⓘ }
Преобразует этот тип в разделяемую ссылку (обычно inferred) входного типа.
AsRef<OsStr> для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn as_ref(&self) -> &OsStr }
Преобразует этот тип в разделяемую ссылку (обычно inferred) входного типа.
AsRef<Path> для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn as_ref(&self) -> &Path }
Преобразует этот тип в разделяемую ссылку (обычно inferred) входного типа.
AsRef<str> для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn as_ref(&self) -> &str }
Преобразует этот тип в разделяемую ссылку (обычно inferred) входного типа.
Borrow<str> для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn borrow(&self) -> &str }
Неизменяемо заимствует из owned значения. Читать далее
BorrowMut<str> для String
Доступность: 1.36.0
Метод
#![allow(unused)] fn main() { fn borrow_mut(&mut self) -> &mut str }
Изменяемо заимствует из owned значения. Читать далее
Clone для String
Доступность: 1.0.0
Методы
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &String) }
Клонирует содержимое source в self.
Этот метод предпочтительнее простого присваивания source.clone() для self, так как он избегает перераспределения, если возможно.
#![allow(unused)] fn main() { fn clone(&self) -> String }
Возвращает дубликат значения. Читать далее
Debug для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера. Читать далее
Default для String
Доступность: 1.0.0 (const: unstable)
Метод
#![allow(unused)] fn main() { fn default() -> String }
Создает пустую String.
Deref для String
Доступность: 1.0.0
Ассоциированный тип
#![allow(unused)] fn main() { type Target = str }
Результирующий тип после разыменования.
Метод
#![allow(unused)] fn main() { fn deref(&self) -> &str }
Разыменовывает значение.
DerefMut для String
Доступность: 1.3.0
Метод
#![allow(unused)] fn main() { fn deref_mut(&mut self) -> &mut str }
Изменяемо разыменовывает значение.
Display для String
Доступность: 1.0.0
Метод
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера. Читать далее
Extend для различных типов
String реализует Extend для различных типов, позволяя эффективное добавление множества элементов.
Доступность: Зависит от конкретной реализации
From для различных типов
String может быть создана из различных типов, включая &str, Box<str>, Cow<str>, char и другие.
Доступность: Зависит от конкретной реализации
FromIterator для различных типов
String может быть создана из итераторов различных типов.
Доступность: Зависит от конкретной реализации
FromStr для String
Доступность: 1.0.0
Ассоциированный тип
#![allow(unused)] fn main() { type Err = Infallible }
Ассоциированная ошибка, которая может быть возвращена из парсинга.
Метод
#![allow(unused)] fn main() { fn from_str(s: &str) -> Result<String, <String as FromStr>::Err> }
Парсит строку s, чтобы вернуть значение этого типа. Читать далее
Hash для String
Доступность: 1.0.0
Методы
#![allow(unused)] fn main() { fn hash<H>(&self, hasher: &mut H) where H: Hasher, }
Подает это значение в заданный Hasher. Читать далее
#![allow(unused)] fn main() { fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher, Self: Sized, }
Подает срез этого типа в заданный Hasher. Читать далее
Index и IndexMut для String
String поддерживает индексацию с помощью типов, реализующих SliceIndex<str>.
Доступность: 1.0.0
Ord и PartialOrd для String
String может быть сравнена с другими String и строковыми срезами.
Доступность: 1.0.0
PartialEq для различных типов
String может быть сравнена на равенство с различными строковыми типами.
Доступность: 1.0.0
Pattern для &String
Удобная реализация, которая делегирует реализации для &str.
Доступность: 1.0.0
ToSocketAddrs для String
Доступность: 1.16.0
Ассоциированный тип
#![allow(unused)] fn main() { type Iter = IntoIter<SocketAddr> }
Возвращенный итератор по сокетным адресам, которым может соответствовать этот тип.
Метод
#![allow(unused)] fn main() { fn to_socket_addrs(&self) -> Result<IntoIter<SocketAddr>> }
Преобразует этот объект в итератор разрешенных SocketAddrs. Читать далее
TryFrom для различных типов
String может быть создана из различных типов с проверкой ошибок.
Доступность: Зависит от конкретной реализации
Write для String
Доступность: 1.0.0
Методы
#![allow(unused)] fn main() { fn write_str(&mut self, s: &str) -> Result<(), Error> }
Записывает срез строки в этот writer, возвращая, удалась ли запись. Читать далее
#![allow(unused)] fn main() { fn write_char(&mut self, c: char) -> Result<(), Error> }
Записывает char в этот writer, возвращая, удалась ли запись. Читать далее
#![allow(unused)] fn main() { fn write_fmt(&mut self, args: Arguments<'_>) -> Result<(), Error> }
Клей для использования макроса write! с implementors этого трейта. Читать далее
Автоматические реализации трейтов
Freeze for StringRefUnwindSafe for StringSend for StringSync for StringUnpin for StringUnwindSafe for String
Особенности производительности
String разработана для эффективной работы со строками:
- Использует
Vec<u8>внутри для хранения данных - Гарантирует валидность UTF-8
- Поддерживает эффективную конкатенацию через
+и+= - Позволяет предварительное выделение памяти с
with_capacity - Поддерживает различные методы преобразования из/в байты
Рекомендации по использованию
- Используйте
&strдля параметров функций, когда возможно - Используйте
String::with_capacityкогда известен ожидаемый размер - Предпочитайте методы
push_strиextendдля добавления данных - Используйте
Cow<str>для гибкой работы со строками, которые могут быть как заимствованными, так и owned